home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / qbgps240.zip / GPS.DOC < prev    next >
Text File  |  1995-01-11  |  132KB  |  2,571 lines

  1.  
  2.  
  3.   Documentation for
  4. ┌───────────────────────────────────────────────────┐
  5. │ GPS (General Purpose Subroutines) Library  <v248> │
  6. │ (c) Garry Spencer / Spencer Technologies          │
  7. │ P.O. Box 34OO9  Memphis, TN  38184-OOO9           │
  8. └───────────────────────────────────────────────────┘
  9.  
  10. ┌───────────────┬─────────────────────────────────┐
  11. │   Number of   │                                 │
  12. │ Functions in  │                                 │
  13. ├───────┬───────┤                                 │
  14. │GPS.LIB│GPS.QLB│  Function Group                 │
  15. ├───────┼───────┼─────────────────────────────────┤
  16. │  24   │  24   │  Date / Time                    │
  17. │  18   │  18   │  DOS (Handle-Based)             │
  18. │  13   │  13   │  File / Directory               │
  19. │   8   │   8   │  Joystick                       │
  20. │  25   │  25   │  Keyboard                       │
  21. │  27   │  27   │  Memory                         │
  22. │  17   │  17   │  Mouse                          │
  23. │  22   │  22   │  Numeric                        │
  24. │  22   │  22   │  Screen (ANSI - text mode only) │
  25. │  32   │  24 * │  Screen (VIDEO- text mode only) │
  26. │  36   │  36   │  String                         │
  27. │   4   │   4   │  System / Miscellaneous         │
  28. ├───────┼───────┼─────────────────────────────────┤
  29. │ 248   │ 24O   │  Total Number of Functions      │
  30. └───────┴───────┴─────────────────────────────────┘
  31. * Note that the GPS.QLB quick-library does NOT support the following 8 routines:
  32.   ColorPDQ, ColorQB, SetColorPDQ, SetColorQB, SetVideoSegPDQ, SetVideoSegQB,
  33.   VideoSegPDQ and VideoSegQB.
  34.  
  35. Warranty: None expressed or implied.
  36.  
  37. The routines in this library have been thoroughly tested with
  38. Quick-BASIC version 4.5, HOWEVER Spencer Technologies and/or any employees
  39. of the company are not liable for the use or misuse of this software.
  40.  
  41. The registered version of this software package is protected under the
  42. copyright laws of the United States of America.  It must not be copied,
  43. transmitted or duplicated in any way.  It is to be used only by the purchaser.
  44.  
  45. INSTRUCTIONS FOR USING THE GPS LIBRARY WITH QUICK-BASIC
  46.  
  47.   The GPS library was designed solely for use with programs written in 
  48. Quick-BASIC.  Some of the routines may work with BASIC PDS or Visual-BASIC
  49. for DOS, however the testing of these routines was limited to programs
  50. written in Quick-BASIC version 4.5 ONLY.  In some of the functions, CALLs
  51. were made to Quick-BASIC's internal routines such as B$ASSN etc.
  52.   The GPS library was also tested with the PDQ (BASIC replacement) library from
  53. Crescent Software, 11 Bailey Ave., Ridgefield, CT O6877 (2O3-438-53OO).
  54. Their PDQ library replaces the BCOM45.LIB (and QB.LIB) libraries and creates
  55. .EXE files about one-half the size of normal Quick-BASIC executable files.
  56. Be sure to make a backup copy of the enclosed diskette (for your own use only).
  57. Note that capital O is used throughout this documentation in place of the
  58. slashed-zero (0).
  59.  
  60. The GPS.QLB quick-library is designed to be used inside the Quick-BASIC
  61. editor/environment (e.g. QB progname /L GPS).
  62. Note that the GPS.QLB quick-library does NOT support the following 8 routines:
  63. ColorPDQ, ColorQB, SetColorPDQ, SetColorQB, SetVideoSegPDQ, SetVideoSegQB,
  64. VideoSegPDQ and VideoSegQB.
  65.  
  66. The GPS.LIB library is designed to be used ONLY from the DOS command line.
  67. Note that each function and/or subroutine in the GPS.LIB library MUST be
  68. declared before it can be used.  There is a file named GPS.BI which is
  69. included on the enclosed diskette.  This file contains the correct DECLARE
  70. statement for each routine in GPS.LIB.  To allow your programs to use this
  71. file, place the following statement in your source code (before any executable
  72. statements).
  73.  
  74. '$Include: '\QB45\GPS.BI'
  75. Note that the single-quotes (') must be included as part of the statement.
  76. The \QB45 directory can be replaced with the appropriate directory name
  77. in which the GPS.BI file resides.  If you wish to copy the individual DECLARE
  78. statements from the GPS.BI file to your source code, you should be extremely
  79. careful to use the BYVAL and SEG keywords wherever they appear.  The under-
  80. score symbol (_) is used at the end of a line in Quick-BASIC to allow the
  81. program line to be continued on the next physical line in the file.  Be sure
  82. to copy the entire DECLARE statement including continuation lines.
  83.  
  84. To compile your program, type the following:
  85.  
  86. BC progname/O;
  87. if you are not using ON ERROR GOTO/RESUME statements
  88.  
  89. BC progname/O/E/X;
  90. if you are using ON ERROR GOTO/RESUME statements 
  91.  
  92. To link your program into an .EXE executable file, type:
  93.  
  94. LINK/EX progname,,nul,\QB45\GPS;
  95. if you are linking with Quick-BASIC's BCOM45.LIB
  96. (assuming that the GPS.LIB file is in the \QB45 directory. You should
  97. obviously use the directory name in which the GPS.LIB file is located.)
  98.  
  99. LINK/EX/NOD/NOE progname,,nul,\PDQ\PDQ \QB45\GPS;
  100. if you are using the PDQ.LIB library from Crescent Software
  101. (assuming that PDQ.LIB is located in the \PDQ directory)
  102.  
  103. SPECIAL PROGRAMMING CONSIDERATIONS
  104.  
  105. Many of the GPS functions use 16-bit (2-byte) integer values as operands or to
  106. return information to your program.  Quick-BASIC's 2-byte integer variables
  107. (such as X%) use 16-bit signed values which have a range of -32768 to +32767.
  108. A 16-bit UNsigned integer can actually represent numbers in the range of O to
  109. +65535.  There is a problem when using (%) type variables to represent numbers
  110. between +32768 and +65535.  For example, the number used to represent the
  111. segment address of the text-mode memory area for a color monitor is 471O4.  
  112. This number is obviously too large to be used in: X% = 471O4%.  You must
  113. therefore, use another method of assigning the value 471O4 to the X% variable.
  114. The methods normally used for this purpose include representing these large
  115. values as hexadecimal numbers or as NEGATIVE numbers.
  116.  
  117. To use hexadecimal: 471O4 is the same as B8OO (hex)
  118. X% = &HB8OO
  119. Note: Many scientific calculators can convert between decimal and hexadecimal.
  120.  
  121. To convert large numbers in the range (+32768 to +65535) to negative values use:
  122. NegativeValue = LargeValue - 65536
  123. For example, 471O4 - 65536 = -18432
  124. X% = -18432%     is the same as    X% = &HB8OO
  125. Note: 65536 is too large to be used as a 2-byte integer in Quick-BASIC programs.
  126.       If the conversion is to be calculated inside a program, use 65536& to
  127.       allow the compiler to treat 65536 as a 4-byte (long) integer.
  128. To convert back from a negative value to a large positive value, use:
  129. LargeValue = NegValue + 65536   (ex. -18432 + 65536 = 471O4)
  130.  
  131. The reason for the problem lies in the way Quick-BASIC uses a 16-bit (2-byte)
  132. number to represent signed values.  The following diagram shows a 16-bit binary
  133. number.  Each N represents a BIT which stands for (BInary-digiT).  Each bit
  134. is either a one (1) or a zero (O) and is a power of two.
  135.  
  136.      16384      4O96      1O24      256       64        16         4         1
  137.   N    N    N    N    N    N    N    N    N    N    N    N    N    N    N    N
  138. 32768      8192      2O48      512       128       32         8         2
  139.  
  140. As you can see, if all bits are ON (i.e. equal to 1) the number would be:
  141. 1111111111111111 binary  =  FFFF (hexadecimal)
  142.      --or--
  143. 1+2+4+8+16+32+64+128+256+512+1O24+2O48+4O96+8192+16384+32768 = 65535 decimal
  144.  
  145. HOWEVER, Quick-BASIC (and the 8Ox86) has designated the most-significant
  146. (leftmost) bit as the SIGN bit, so that it no longer means 32768 in signed
  147. 2-byte integers.
  148. If the sign bit is zero (O), the signed number is considered to be positive,
  149. therefore:
  150. O111111111111111 binary  =  7FFF (hexadecimal)
  151.      --or--
  152. 1+2+4+8+16+32+64+128+256+512+1O24+2O48+4O96+8192+16384 = 32767 decimal
  153.  
  154. If the sign bit is one (1), the signed number is considered to be negative,
  155. and is stored in 2s complement form.  For example, 
  156. 1111111111111111  =  FFFF (hexadecimal)
  157. the sign bit is a one (1) therefore the number is negative and in 2s complement
  158. form.  The number shown is -1 (in decimal).  Convert from/to 2s complement form
  159. by complementing (inverting) all bits (1s complement), then add 1 to the result.
  160.  
  161. SPECIAL PROGRAMMING CONSIDERATIONS (Continued)
  162.  
  163. Segmented Memory Addressing
  164.  
  165. Some of the microprocessors used in IBM-compatible computers (8O386+) can
  166. address all of the available memory space in a linear manner.  The earlier
  167. processors (8O88, 8O86 etc) were designed to address memory in segments.
  168. The latest processors (Pentium etc.) can still be used to address memory which
  169. has been laid out in segments, therefore it is necessary to mention this 
  170. method of memory access in this documentation.
  171.  
  172. A typical segmented memory address has the following form:
  173.  
  174. pppp:oooo where pppp is the paragraph (segment) and oooo is the offset
  175.           within that segment.  Note that both numbers are shown in
  176.           4-digit hexadecimal form.
  177.  
  178. The actual memory address can be found by multiplying the paragraph by
  179. 16 (1O hex) and then adding the offset to that number.  For example,
  180.  
  181. segmented memory address 1742:4982 (hexadecimal) means that the paragraph is
  182. 1742 (hex) and the offset is 4982 (hex).  Calculating the actual address,
  183.  
  184. (1742 x 1O = 1742O) + 4982 = 1BDA2 (the actual address in hexadecimal)
  185.  
  186. It is intuitively obvious to even the most casual observer, that each 
  187. paragraph can only start on a memory location which is evenly divisible
  188. by 16.  From that starting address, it is possible to address up to 64k
  189. (O to 65535) different memory locations (byte-wide).  The accepted 
  190. terminology, used in most literature, dictates that a paragraph of memory is
  191. 16 bytes long and that a segment of memory can be up to 64k (65536) bytes
  192. in length.  Sometimes the terms paragraph and segment are used to represent
  193. the same thing, but it is usually apparent which meaning these terms have in
  194. context.
  195.  
  196. To find the actual memory location of a variable, the Quick-BASIC commands
  197. VARSEG and VARPTR can be used.  VARSEG finds the segment in which the variable
  198. resides and VARPTR finds the offset (pointer) from the start of that segment.
  199. Note that Quick-BASIC's default data segment is called DGROUP.
  200.  
  201. A% = 1
  202. MemSeg% = VARSEG ( A% )   'find the segment in which A% resides
  203. MemPtr% = VARPTR ( A% )   'find the offset (pointer)
  204.  
  205. In this example, the variable (A%) is located at segment MemSeg% and at
  206. offset (pointer) MemPtr%.  Please note that for each memory location, there
  207. are several combinations of segment and offset addresses which could point to
  208. that actual memory location.  For example,
  209.  
  210. 2415:OO11 is the same as 2416:OOO1 (in hexadecimal).  It is possible to
  211. minimize the offset (pointer) by adding 1 to the segment while subtracting 
  212. 16 (1O hex) from the offset.  If this is done repeatedly, the offset can be
  213. reduced to the range (O to 15) or (O to F hex).  This is exactly what the
  214. GPS library function MinimizePtr does.  The function VarSegPtr also returns
  215. a minimized offset/segment combination for a given variable.  If your program
  216. will be copying large blocks of memory, it would be best to minimize the
  217. offset (pointer) before using GPS functions like MemCopy etc.  This will
  218. prevent a problem with overflow on the (DS:SI and/or ES:DI) internal registers.
  219.  
  220. SPECIAL PROGRAMMING CONSIDERATIONS (Continued)
  221.  
  222. Variable-Length Strings vs Fixed-Length Strings
  223.  
  224. Many of the routines in the GPS.LIB library require a string as an operand.
  225. DO NOT use a fixed-length string for ANY of these operands (arguments).  The
  226. reason for this is that Quick-BASIC stores these two string types differently.
  227. A fixed-length string is basically a block of memory which can either reside
  228. in DGROUP (default data segment) or in the far heap (outside DGROUP).  A
  229. Quick-BASIC variable-length string, such as X$, must reside in DGROUP.  In
  230. order to keep the assembly language code size small, it was assumed that all
  231. string operands were variable-length ($) string types.  A quoted string, like
  232. "text string" is also stored (as a constant) in variable-length string format,
  233. so that this type can also be used as an operand.  Note that some routines
  234. actually change the operand string directly (e.g. UpperCase).  For these
  235. routines you should NOT use a quoted string constant, such as "Text".
  236.  
  237. An example of each string type is given below:
  238.  
  239. DIM TXT AS STRING*5O
  240. TXT is a fixed-length string and should NEVER be used as a string operand.
  241. The statement: Call UpperCase ( TXT )   would therefore be illegal.
  242.  
  243. "The quick brown fox" is a quoted string which is stored like a variable-length
  244. string and can be used as a string operand for MOST but not all routines.  This
  245. string type may NOT be used in routines which change the string directly,
  246. such as ChgMid, LowerCase, Replace, and UpperCase.
  247.  
  248. TextString$ is a variable-length string which can be used as an operand in ANY
  249. of the GPS.LIB routines.
  250.  
  251. Note that a fixed-length string can be used to receive the return value of a
  252. string function.  For example, the following program code is correct:
  253. DIM TXT AS STRING*34
  254. TXT=FindFile$ ( O, "*.BAS", 7) 
  255.  
  256. SPECIAL PROGRAMMING CONSIDERATIONS (Continued)
  257.  
  258. A Quick-BASIC variable-length string is stored in the following manner:
  259.  
  260. ┌──────┬──────┬──────┬──────┐ 
  261. │    Length   │  Location   │
  262. └──────┴──────┴──────┴──────┘
  263. └─────────────┬─────────────┘
  264.               │
  265. This is a 4-byte string descriptor for a variable-length string.
  266. The string descriptor is made up of 2 bytes for the string length and 2 bytes
  267. for the location (offset within the DGROUP segment) of the first byte of the
  268. actual string data. 
  269.  
  270. ┌──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬──────┬─∙∙∙∙∙
  271. │ Back Pointer│  Actual string data would be placed here .....
  272. └──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴──────┴─∙∙∙∙∙
  273. The back pointer (which ALWAYS immediately precedes the actual string data
  274. in memory) points to the memory location of the first byte of the string
  275. descriptor (shown above).  The back pointer is used by Quick-BASIC to allow
  276. clean-up of the string data area.  Quick-BASIC examines the back pointers and
  277. each back pointer allows Quick-BASIC to find the string descriptor belonging
  278. to the back pointer's accompanying string data.  If the string descriptor
  279. (pointed to by a back pointer) no longer points to the actual string data, then
  280. Quick-BASIC knows that the memory block occupied by the string data can be
  281. reclaimed for other strings etc.
  282.  
  283. The 64k-byte DGROUP segment, which holds the string descriptor, the back pointer
  284. and the actual string data, can be determined by the following statement.
  285. DGROUP% = VARSEG(TextString$)
  286.  
  287. The location of the first byte of the string descriptor is found as follows:
  288. StrDesc% = VARPTR(TextString$)
  289.  
  290. The location of the first byte of the actual string data is found by:
  291. StrData% = SADD(TextString$)
  292.  
  293. The following program code shows how to access each part of the string
  294. (TextString$).
  295.  
  296. DGROUP%  = VARSEG(TextString$) 'finds the default data segment DGROUP
  297. DEF SEG  = DGROUP% 'make PEEKs/POKEs use DGROUP segment
  298. StrDesc% = VARPTR(TextString$) 'finds address of 1st byte of string descriptor
  299. Length%  = 256% * PEEK(StrDesc%+1) + PEEK(StrDesc%)
  300. StrData% = SADD(TextString$)   'finds address of 1st byte of actual string data
  301. StrData% = 256% * PEEK(StrDesc%+3) + PEEK(StrDesc%+2) 'another way to find it
  302. BackPtr% = StrDesc%   'the same for an active string (address of descriptor)
  303. BackPtr% = 256% * PEEK(StrData%-1) + PEEK(StrData%-2) 'another way to find it
  304.  
  305. Note: The back pointer itself (BackPtr%) holds the ADDRESS (within DGROUP) of
  306.       the first byte of the string descriptor.
  307.  
  308. SPECIAL PROGRAMMING CONSIDERATIONS (Continued)
  309.  
  310. Text Screen Color Attribute Byte
  311.  
  312. The screen subroutines and functions, in the GPS library, are to be used in
  313. text-mode only (SCREEN O).  These routines use direct video memory writes to
  314. update the screen.  You will notice that some of these routines require a
  315. color attribute byte operand.
  316. The format for this byte is as follows (shown as an 8-bit binary number):
  317.  
  318. Blink Bit       High-Intensity (Bright) Bit
  319.     │                       │
  320.   ┌─┴─┐                   ┌─┴─┐
  321.     N     N     N     N     N     N     N     N
  322.         └───────┬───────┘ └──────────┬──────────┘
  323.                 │                    │
  324.          Background Color     Foreground color
  325.             ( O to 7 )     ( O to 7  for normal )
  326.                            ( 8 to 15 for bright )
  327. The basic colors are:
  328. O = black                  8 = dark gray
  329. 1 = blue                   9 = bright blue
  330. 2 = green                 1O = bright green
  331. 3 = cyan                  11 = bright cyan
  332. 4 = red                   12 = bright red
  333. 5 = magenta (purple)      13 = bright magenta (purple)
  334. 6 = brown                 14 = bright yellow
  335. 7 = white / gray          15 = bright white
  336.  
  337. Note: The Quick-BASIC command:
  338.       COLOR foreground,background
  339.       uses numbers 16 to 31 as blinking foreground colors. (16 + foreground)
  340.  
  341. You can use the GPS library function ColorAttr% to calculate the value of the
  342. attribute byte.  If Foreground% represents Quick-BASIC's foreground color
  343. (O to 31) and Background% represents the background color (O to 7), then the
  344. following line of code will calculate the correct color attribute byte.
  345.  
  346. ColorAttributeByte% = ColorAttr% ( Foreground% , Background% )
  347.  
  348.  
  349. If the value of a color attribute byte is known, and you wish to separate
  350. it into separate foreground and background colors, use the following command:
  351.  
  352. Call AttrColor ( ColorAttributeByte% , Foreground% , Background% )
  353. -----or the alternate form of calling a subroutine-----
  354. AttrColor ColorAttributeByte% , Foreground% , Background%
  355.  
  356. SPECIAL PROGRAMMING CONSIDERATIONS (Continued)
  357.  
  358. Special Note:
  359.  
  360. Quick-BASIC version 4.5 supports the use of alphanumeric labels.  It is no
  361. longer necessary to use line numbers.  This is good news for programmers,
  362. however it can cause a minor problem when using external subroutines such as
  363. the ones in the GPS library.  Here is the problem:
  364.  
  365. There are two ways to call a subroutine in Quick-BASIC.  The first method is
  366. to use the CALL keyword and enclose the operands (if any) in parentheses.
  367. For example,
  368.  
  369. Call NumLockOff
  370. Call AttrColor(Attr%,Fore%,Back%)
  371.  
  372. The second method of calling these subroutines is to simply use the name of the
  373. subroutine followed by the operands (no parentheses).
  374.  
  375. NumLockOff
  376. AttrColor Attr%,Fore%,Back%
  377.  
  378. Both of these methods work, but since Quick-BASIC allows multiple statements
  379. per line by using a colon (:) and it also uses the colon (:) at the end of an
  380. alphanumeric label, Quick-BASIC can sometimes get confused if you use the
  381. second method of calling a subroutine (with no operands) and try to place
  382. another statement on the same line using a colon (:).  For example,
  383.  
  384. NumLockOff : Call AttrColor(Attr%,Fore%,Back%)
  385.  
  386. Quick-BASIC will think that NumLockOff is a label even though there is a
  387. space between it and the colon (:).  This is a problem even when the 
  388. subroutine has been previously declared.  You should either put NumLockOff
  389. on a separate line or use the Call NumLockOff format.  This is a minor problem
  390. that only occurs if the subroutine has no operands.
  391.  
  392. Special Note: In an attempt to keep code size small, error checking on 
  393. operands (e.g. screen row and column) was kept to a minimum. If the
  394. documentation shows the limits on a particular function, your calling program
  395. should make sure that no out-of-bounds operands are supplied to the functions.
  396.  
  397. SPECIAL PROGRAMMING CONSIDERATIONS (Continued)
  398.  
  399. USING THE ALIAS KEYWORD IN A DECLARE STATEMENT
  400.  
  401. The ALIAS keyword allows you to substitute the name of one of Quick-BASIC's
  402. internal functions/subroutines in the place of your routine.  This is necessary
  403. in most cases because many of Quick-BASIC's internal routines use the
  404. ($) dollar-sign or the (_) underscore in the function name.
  405.  
  406. For example, pass an an ERRORLEVEL to DOS on exit from your program.
  407. The DECLARE tells Quick-BASIC to substitute _exit for the EndERRLevel statement.
  408. '------------------------------------------------------------------------------
  409. 'In Quick-BASIC use this:
  410.  
  411. DECLARE SUB EndERRLevel ALIAS "_exit" (BYVAL ErrorLevel%)
  412.  
  413. EndERRLevel 15  'this would end your program and also pass the number 15
  414.                 'to DOS as the ERRORLEVEL variable which could then be
  415.                 'tested in a batch file with the IF ERRORLEVEL statement
  416.  
  417. 'Note: This particular routine (_exit) will only work when compiled to an
  418.       .EXE file from the command line.
  419. '------------------------------------------------------------------------------
  420.  
  421. '------------------------------------------------------------------------------
  422. 'In PDQ you MUST use PDQ's ErrLevel Statement (no alias)
  423.  
  424. DECLARE SUB ErrLevel (ErrorLevel%)
  425.  
  426. EndLevel 15     'this would end your program and also pass the number 15
  427.                 'to DOS as the ERRORLEVEL variable which could then be
  428.                 'tested in a batch file with the IF ERRORLEVEL statement
  429. '------------------------------------------------------------------------------
  430.  
  431. Some additional examples are shown below:
  432.  
  433. DECLARE SUB FileRead  ALIAS "B$GET4" (BYVAL FileNum%, BYVAL FilePosition&, _
  434.                                       BYVAL MemSegment%, BYVAL MemOffset%, _
  435.                                       BYVAL NumberOfBytes%)
  436. DECLARE SUB FileWrite ALIAS "B$PUT4" (BYVAL FileNum%, BYVAL FilePosition&, _
  437.                                       BYVAL MemSegment%, BYVAL MemOffset%, _
  438.                                       BYVAL NumberOfBytes%)
  439.  
  440. OPEN "Test.Dat" FOR BINARY AS BASICFileNumber%
  441.  
  442. FileRead  BASICFileNumber%,FilePosition&,MemSegment%,MemOffset%,NumberOfBytes%)
  443. FileWrite BASICFileNumber%,FilePosition&,MemSegment%,MemOffset%,NumberOfBytes%)
  444.  
  445. These two routines will read-from/write-to a file opened in BINARY mode.
  446. Data is transferred directly between the file and memory (segment:offset).
  447.  
  448. ┌─────────────────────────────────────────────────────────────────────────────┐
  449. │         DATE / TIME FUNCTIONS                                               │
  450. └─────────────────────────────────────────────────────────────────────────────┘
  451. FUNCTION: DayOfWeek% (AnyDate$) 
  452. Returns the day of the week (O=Sunday ... 6=Saturday) for the specified date
  453. in MM-DD-YYYY form.  Note: MM is month (1 to 12), DD is day (1 to 31) and YYYY
  454. is the year (198O to 21O7).  The date must be on or after O1-O1-198O.  If an
  455. incorrect date is specified, the program will be halted by "Illegal Function
  456. Call" caused by BASIC's (B$SDAT routine).
  457. example: Day%=DayOfWeek%("12-31-1999")
  458.  
  459. FUNCTION: DayStr$ (WkDay%)
  460. Returns a string containing the day of the week specified by WkDay% (O to 6).
  461. example: A$=DayStr$(O) 'A$ would be "Sunday"   (note the mixed case)
  462.          A$=DayStr$(6) 'A$ would be "Saturday"
  463.  
  464. FUNCTION: DayWeek% (Mon%, Day%, Year%)
  465. Returns the day of the week (O=Sunday ... 6=Saturday) for the specified date.
  466. Note: Do not use MONTH% as a variable.  The year must be in the range 198O to
  467. 21O7.  If an incorrect date is specified, the function will return -1 (error).
  468. example: DWeek% = DayWeek%(12,31,1999)
  469. Note: If you need to use a year outside 198O to 21O7, then use the WeekDay%
  470.       function.
  471.  
  472. FUNCTION: EventDone%
  473. Checks the status of the last EventSet subroutine call.  If EventDone% is zero,
  474. it means the event timer is still running.  If it is equal to -1, it signals
  475. that the timer has finished its timed interval.  (see EventSet subroutine)
  476.  
  477. SUBROUTINE: EventSet Microseconds&
  478. Starts the event timer with a value in microseconds.  The status of the event
  479. can be checked using the EventDone% function.
  480. For example: (note: 1 microsecond = 1 millionth of a second)
  481. EventSet 1OOOOO& '1OOOOO microseconds is the same as .1 sec
  482. While Not EventDone%
  483. 'your statements here will continuously execute for .1 seconds
  484. Wend
  485.  
  486. SUBROUTINE: EventWait Microseconds&
  487. Starts the event timer with a value in microseconds.  This routine differs from
  488. EventSet in that EventWait does not return to the calling program until the
  489. event timer interval has elapsed.
  490. example: EventWait 5OOOOO& 'wait here for one-half second
  491.  
  492. SUBROUTINE: GetDate Mon%, Day%, Year%, DWeek%
  493. Returns the month, day, year and day-of-week into the specified variables.
  494. Notes: For DWeek%  O=Sunday ... 6=Saturday
  495.        Do not use MONTH% as a variable.
  496. example: GetDate MM%,DD%,YY%,DWk%
  497.  
  498. SUBROUTINE: GetTime Hrs%, Min%, Sec%, HSec%
  499. Returns the hours (O to 23), minutes, seconds and hundredths-of-seconds into
  500. the specified variables.  Note: The time is only updated 18.2 times per second.
  501. example: GetTime HH%,MM%,SS%,S1OO%
  502.  
  503. SUBROUTINE: Hibernate TickVal%
  504. Causes program execution to pause for a length of time equal to the specified
  505. number of timer ticks.  Key presses are ignored during the paused state.
  506. Note: There are approximately 18.2 timer ticks in one second.
  507. example: Hibernate 91% 'pause for 5 seconds
  508.  
  509. FUNCTION: LongDate$ (Date2Byte$)
  510. Expands a previously compressed 2-byte date string into a 1O-byte date string
  511. with the form MM-DD-YYYY (month-day-year).  This function should only be used
  512. with the ShortDate$ function.  NO error checking is performed on the date!
  513.  
  514. FUNCTION: LongTime$(TwoByte$)
  515. Expands a previously compressed 2-byte time string into a 5-byte time string
  516. with the form HH:MM (24-hour format).  This function should only be used with
  517. the ShortTime$ function.  NO error checking is performed on the time!
  518.  
  519. FUNCTION: MonthStr$ (MonthVal%)
  520. Returns a string containing the month name specified by MonthVal% (1 to 12).
  521. example: A$=MonthStr$(1)  'A$ would be "January"  (note the mixed case)
  522.          A$=MonthStr$(12) 'A$ would be "December"
  523.  
  524. FUNCTION: SetDate% (Mon%, Day%, Year%)
  525. Sets the current date to the specified month, day and year.  Note: Do not
  526. use MONTH% as a variable.  The year must be in the range of 198O to 21O7.
  527. This function returns zero if the specified date is valid, otherwise it 
  528. returns -1 (error).
  529. example: X%=SetDate%(12,31,1999) 'sets date to 12-31-1999
  530.         'X%=O if o.k.   X%=-1 if error
  531.  
  532. FUNCTION: SetTime% (Hrs%, Min%, Sec%, HSec%)
  533. Sets the current time to the specified hours (O to 23), minutes, seconds and
  534. hundredths-of-seconds.  This function returns zero if the specified time is
  535. valid, otherwise it returns -1 (error).
  536. example: X%=SetTime%(23,45,33,25) 'sets time to 23:45:33.25
  537.         'X%=O if o.k.   X%=-1 if error
  538.  
  539. FUNCTION: ShortDate$ (AnyDate$)
  540. Compresses the given 1O-byte date string (MM-DD-YYYY form) into a 2-byte string
  541. which can then be stored in a file etc.  The 2-byte resultant string can be
  542. used in a chronological sort routine.  This function should be used with
  543. with the LongDate$ function. NO error checking is performed on the date.
  544. example:  SDate$=ShortDate$("12-31-1999")
  545.           LDate$=LongDate$(SDate$)
  546.  
  547. FUNCTION: ShortTime$ (Time24$)
  548. Compresses the given 5-byte time string (HH:MM 24-hour format) into a 2-byte
  549. string which can then be stored in a file etc.  The 2-byte resultant string
  550. can be used in a chronological sort routine.  This function should be used
  551. with the LongTime$ function.  NO error checking is performed on the time.
  552. example: STime$=ShortTime$("23:59")
  553.          LTime$=LongTime$(STime$)
  554.  
  555. FUNCTION: Snooze% (TickVal%)
  556. Causes program execution to pause for a length of time equal to the specified
  557. number of timer ticks or until a key is pressed.  This function has a return
  558. value equal to the keycode (if any) used to prematurely end the delay.  See the
  559. keycode table in the appendix.  Note: There are approximately 18.2 timer ticks
  560. in one second.
  561. example: X%=Snooze%(91%) 'pause for 5 seconds or until a key is pressed
  562.  
  563. FUNCTION: TickTime$ (TickValue&)
  564. This function converts the specified number of timer ticks (TickValue&) into
  565. an 8-byte time string in HH:MM:SS form.  (note: HH = OO to 23)
  566. There are approximately 18.2 timer ticks in one second and approximately
  567. 1O92 ticks in one minute.  The maximum number of ticks in one day is 1573O39.
  568. example1:   T$=TickTime$(Timr&) 'uses Timr& function and would return the same
  569.                                 'string as BASIC's TIME$ function.
  570. example2:   TLimit&= (15& * 1O92&)             'time limit is 15 minutes
  571.             TimerReset 3                       'reset timer#3
  572.       Temp: TRemain& = TLimit& - TimerRead&(3) 'calculate time remaining
  573.             If TRemain& <= O GoTo Quit
  574.             Locate 1,1 : Print TickTime$(TRemain&) 'print countdown time     
  575.             GoTo Temp
  576.       Quit: 'continue program here after time has expired
  577.  
  578. FUNCTION:   TimerRead& (TimerNumber%)
  579. SUBROUTINE: TimerReset TimerNumber%
  580. TimerRead& returns the number of timer ticks since the specified TimerNumber%
  581. was reset (using the TimerReset subroutine).  The TimerNumber% should be in 
  582. the range (O to 15).  If the TimerReset subroutine is called, with a
  583. TimerNumber% outside the range (O to 15), then ALL 16 timers (O to 15) will be
  584. reset to zero.  There are approximately 18.2 timer ticks in one second.
  585. example:  TimerReset -1  'reset ALL 16 timers to zero
  586.           TimerReset 16  'reset ALL 16 timers to zero
  587.           TimerReset  O  'reset only timer number O  to zero
  588.           TimerReset 15  'reset only timer number 15 to zero
  589.    TMRO&= TimerRead&(O)  'TMRO&  set to number of ticks since timer O  was reset
  590.    TMR15&=TimerRead&(15) 'TMR15& set to number of ticks since timer 15 was reset
  591. Note: Attempting to read outside the range (O to 15) will return unpredictable
  592.       values.  These routines correctly handle the timer tick "roll-over" at
  593.       midnight, but each timer will only be valid for up to 24 hours after it
  594.       is reset to zero.
  595.  
  596. FUNCTION:   TmrRd& ( TimerVariable&)
  597. SUBROUTINE: TmrRst TimerVariable&
  598. These routines are basically the same as the TimerRead& and TimerReset 
  599. routines, except that a long-integer variable is used to store the timer value
  600. instead of using an internal storage area.  This allows an essentially 
  601. unlimited number of timers to be used.
  602. example: TmrRst TimerVar&
  603.          While TmrRd&(TimerVar&)<1OO : Wend 'wait here for 1OO timer ticks
  604.  
  605. FUNCTION: Timr&
  606. Returns the number of timer ticks since midnight.  Note: There are
  607. approximately 18.2 timer ticks in one second.
  608. example: Ticks& = Timr&  'this returns a long integer
  609.  
  610. FUNCTION: WeekDay% (Mon%, Day%, Year%)
  611. This function is identical to the DayWeek% function except that it accepts
  612. any year in the range (1582 A.D. to 245O A.D.).  The reason that these two
  613. functions (DayWeek% and WeekDay%) are both included in this library, is that
  614. the WeekDay% is a bit larger than DayWeek% and should only be used when a year
  615. outside the 198O to 21O7 range is to be specified.  This function returns
  616. O=Sunday...6=Saturday, and it returns -1 if an error occurs (i.e. illegal date).
  617. example:  A%=WeekDay%(7,4,1776) 'A% is the day of the week on which the
  618.                                 'Declaration of Independence was signed
  619.                                 'on July 4, 1776.
  620.  
  621. ┌─────────────────────────────────────────────────────────────────────────────┐
  622. │         DOS (Handle-Based) FUNCTIONS                                        │
  623. └─────────────────────────────────────────────────────────────────────────────┘
  624. The routines in this section use the standard DOS services to access files.
  625.  
  626. When a file is opened, using the DOSOpen routine, DOS assigns a unique "handle"
  627. to that file. Note: This handle number is --NOT-- the same thing as BASIC's file
  628. number!  Your program must keep track of the handle number after a file is
  629. opened.
  630.  
  631. The DOSRtnErr% function must be DECLAREd in your program
  632. (or '$include: 'gps.bi') because it is the only way to determine if an error
  633. occurred during execution of any of the GPS library DOS routines. Note: ALL of
  634. the GPS library DOS routines modify the DOSRtnErr% value (except, of course,
  635. the DOSRtnErr% routine itself).
  636.  
  637. SUBROUTINE: DOSClose Handle%
  638. This routine closes the file belonging to the specified handle.
  639. ex: DOSOpen "Temp.Fil",O,1,Handle%
  640.     DOSClose Handle%
  641.  
  642. SUBROUTINE: DOSDel FileName$
  643. This routine deletes the specified file.  Note that this routine uses the
  644. actual filename instead of a handle.
  645. ex: DOSDel "Temp.Fil"
  646.  
  647. FUNCTION: DOSFAttr% (FileName$)
  648. Returns the DOS File Attribute byte value for the specified file. The bit 
  649. values of this byte are as follows:
  650. Bit O  -  Binary Value=   1  -  Read_Only File
  651. Bit 1  -  Binary Value=   2  -  Hidden File
  652. Bit 2  -  Binary Value=   4  -  System File
  653. Bit 3  -  Binary Value=   8  -  Volume Name
  654. Bit 4  -  Binary Value=  16  -  Directory Name
  655. Bit 5  -  Binary Value=  32  -  Archive Bit
  656. Bit 6  -  Binary Value=  64  -  <reserved>
  657. Bit 7  -  Binary Value= 128  -  <reserved>
  658. Note that this function uses the actual filename instead of a handle.
  659. ex: Attributes% = DOSFAttr% ("Temp.Fil") 'get the attributes for a file
  660.  
  661. SUBROUTINE: DOSFAttrSet FileName$, AttributeByte%
  662. Sets the DOS File Attribute Byte for the specified file using the value of
  663. AttributeByte%. See the DOSFAttr% function for a description of this byte.
  664. Note that this subroutine uses the actual filename instead of a handle.
  665. ex: Attributes% = DOSFAttr% ("Temp.Fil")
  666.     DOSFAttrSet "Temp.Fil", (Attributes% OR 1) 'make the file read-only
  667.  
  668. SUBROUTINE: DOSFDateGet Handle%, Mon%, Day%, Year%, Hr%, Min%, Sec%
  669. This routine retrieves the date and time for the file whose handle is specified.
  670. Note: The 24-hour system is used for Hr% (i.e. OO to 23).
  671. ex: DOSOpen "Temp.Fil",O,1,Handle%
  672.     DOSFDateGet Handle%,Month%,Day%,Year%,Hour%,Minute%,Second%
  673.     DOSClose Handle%
  674.  
  675. SUBROUTINE: DOSFDateSet Handle%, Mon%, Day%, Year%, Hr%, Min%, Sec%
  676. This routine sets the date and time for the file whose handle is specified.
  677. Note: The 24-hour system is used for Hr% (i.e. OO to 23). The seconds must be
  678. an even number. The year must be 198O or later.
  679. ex: DOSOpen "Temp.Fil",O,1,Handle%
  680.     DOSFDateGet Handle%,Month%,Day%,Year%,Hour%,Minute%,Second%
  681.     DOSFDateSet Handle%,Month%,Day%,Year%,O,O,O 'set file time to midnight OO:OO
  682.     DOSClose Handle%
  683.     'Note: The DOSFDateGet routine was used first because it was necessary
  684.     '      in order to preserve the month, day and year.
  685.  
  686. FUNCTION: DOSFPtr& (Handle%)
  687. This routine retrieves the file pointer for the file whose handle is specified.
  688. The file pointer is the place in the file where the next file read or write
  689. would occur. Note that the beginning of the file is at pointer value=O.
  690. ex: FilePointer& = DOSFPtr&(Handle%) : Print FilePointer&
  691.  
  692. SUBROUTINE: DOSFPtrMove Handle%, PtrMovement&
  693. This routine moves the file pointer by the number of bytes specified by
  694. PtrMovement& for the file whose handle is specified. If PtrMovement& is positive
  695. then the movement is forward. If PtrMovement& is negative then the movement is
  696. backwards. Note that the beginning of the file is at pointer value=O.
  697. ex: DOSFPtrMove Handle%, 16 'move file pointer forward by 16 bytes
  698.     DOSFPtrMove Handle%,-12 'move file pointer backwards by 12 bytes
  699.  
  700. SUBROUTINE: DOSFPtrSet Handle%, NewPtr&
  701. This routine sets the file pointer to the position specified by NewPtr& for
  702. the file whose handle is specified. Note that the beginning of the file is at
  703. pointer value=O.
  704. ex: DOSFPtrSet Handle%,O         'set the pointer to the beginning of the file 
  705.     FileSize&=DOSFSize&(Handle%)
  706.     DOSFPtrSet Handle%,FileSize& 'set the pointer to the end of the file 
  707.                                  'for append mode operation
  708.  
  709. FUNCTION: DOSFSize& (Handle%)
  710. Returns the file size of the file whose handle is specified.
  711. ex: DOSOpen "Temp.Fil",O,1,Handle%
  712.     FileSize& = DOSFSize&(Handle%)
  713.     DOSClose Handle%
  714.  
  715. SUBROUTINE: DOSOpen FileName$, ReadWrite%, InitPtr%, Handle%
  716. Opens the specified file and assigns its handle to the Handle% variable.
  717. The ReadWrite% value should be specified as O=read-only, 1=write-only and
  718. 2=read-write.  The InitPtr% should be specified to instruct DOS where the
  719. DOS file pointer should be positioned for this file, O=truncate file to
  720. zero length (only if ReadWrite%>O), 1=point to beginning of file and 
  721. 2=point to end of file.
  722. ex: DOSOpen "Temp.Fil",O,1,Handle%
  723.     'opens the file as read-only and points to the beginning of the file
  724.     'and assigns its handle to the Handle% variable
  725.  
  726. SUBROUTINE: DOSRdMem Handle%, MSeg%, MPtr%, NBytes%
  727. SUBROUTINE: DOSRdStr Handle%, Text$, NBytes%
  728. SUBROUTINE: DOSRdVar Handle%, AnyVariable, NBytes%
  729. These routines read data from the file, whose handle is specified, starting at
  730. the current position of the file pointer. The first form (DOSRdMem) reads the
  731. specified number of bytes, from the file, into the segmented memory address
  732. MSeg%:MPtr%. The second form (DOSRdStr) reads the specified number of bytes,
  733. from the file, into a variable-length string variable Text$.  The third form
  734. (DOSRdVar) reads the specified number of bytes, from the file, into a normal
  735. variable or a TYPE variable.
  736. ex: DOSRdMem Handle%,&hB8OO,O,4OOO 'reads a 4OOO-byte screen image into the
  737.                                    'color (text) video memory segment from file
  738.     DOSRdStr Handle%,XYZ$,123 'reads 123 bytes into the XYZ$ string from file
  739.     DOSRdVar Handle%,A%(O),9O 'reads 45 values (2 bytes each) into integer
  740.                               'array A%() from file
  741.                               'note: array must first be dimensioned
  742.  
  743. FUNCTION: DOSRtnErr%
  744. Returns zero if the last GPS library DOS routine did not result in an error,
  745. otherwise the actual DOS error number is returned.
  746. ex: DOSOpen "FileName.Ext",O,1,Handle%
  747.     ErrorInDOS% = DOSRtnErr%
  748.     If ErrorInDOS%<>O Then Print "DOS Error Number ";ErrorInDOS% : Goto Halt
  749.  
  750. SUBROUTINE: DOSWrtMem Handle%, MSeg%, MPtr%, NBytes%
  751. SUBROUTINE: DOSWrtStr Handle%, Text$
  752. SUBROUTINE: DOSWrtVar Handle%, AnyVariable, NBytes%
  753. These routines write data to the file, whose handle is specified, starting at
  754. the current position of the file pointer. The first form (DOSWrtMem) writes the
  755. specified number of bytes, to the file, from the segmented memory address
  756. MSeg%:MPtr%. The second form (DOSWrtStr) writes the contents of the
  757. variable-length string Text$ to the file.  The third form (DOSWrtVar) writes
  758. the specified number of bytes, to the file, from a normal variable or a TYPE
  759. variable.
  760. ex: DOSWrtMem Handle%,&hB8OO,O,4OOO 'writes a 4OOO-byte screen image from the
  761.                                     'color (text) video memory segment to file
  762.     DOSWrtStr Handle%,XYZ$ 'writes the XYZ$ string to the file (no cr-lf added)
  763.     DOSWrtVar Handle%,A%(O),9O 'writes 45 values (2 bytes each) from integer
  764.                               'array A%() to file
  765.                               'note: array must first be dimensioned
  766.  
  767. ┌─────────────────────────────────────────────────────────────────────────────┐
  768. │         FILE / DIRECTORY FUNCTIONS                                          │
  769. └─────────────────────────────────────────────────────────────────────────────┘
  770. SUBROUTINE: ChgDir NewDir$
  771. Changes the default directory to the one specified.  If the drive is different
  772. from the current drive, it is also changed.  Note: BASIC's CHDIR command will
  773. not change the default drive.
  774. example: ChgDir "A:"    'changes ONLY the drive
  775.          ChgDir "A:\"   'changes the drive and directory
  776.  
  777. FUNCTION: CurrentDir$
  778. Returns the current default directory including drive.
  779. example: ChgDir "C:\"
  780.          A$=CurrentDir$
  781.          ChgDir "\TEMP"
  782.          B$=CurrentDir$
  783.          Print A$,B$
  784. result:  C:\     C:\TEMP        
  785.  
  786. FUNCTION: DirExist%  (FileName$)
  787. Returns -1 if the specified directory exists and returns zero (O) if it doesn't.
  788. Note: If a critical error occurs (drive door open etc.) the critical error
  789. message (Abort - Retry - Fail) will still appear on the screen.
  790. Exist%=DirExist%("C:\TEMP")
  791.  
  792. FUNCTION: DriveDir$ (Drive%)
  793. Returns the current default directory on the specified drive:
  794. O=current drive  1=A:  2=B:  3=C: etc.
  795. example: A$=DriveDir$(3)
  796.          print A$
  797. result:  C:\TEMP
  798.  
  799. FUNCTION: FileExist% (FileName$)
  800. Returns -1 if the specified file exists and returns zero (O) if it doesn't.
  801. Note: If a critical error occurs (drive door open etc.) the critical error
  802. message (Abort - Retry - Fail) will still appear on the screen.
  803. Exist%=FileExist%("C:\TEMP\MISC.DAT")
  804.  
  805. SUBROUTINE: FileToMem FileNum%,MemSeg%,MemAdr%,NumBytes%
  806. Copies the specified number of bytes (NumBytes%) from a file (at the current
  807. file pointer location) directly into memory at paragraph (MemSeg%) and offset
  808. (MemAdr%).  The FileNum% is BASIC's file number (not the file handle).  The file
  809. must already be opened in Binary Access Read mode.
  810. example: 
  811. 'Copy 4OOO bytes from the beginning of a file to video memory
  812. Open "Temp.SCN" for Binary Access Read as #1
  813. FileToMem 1,&HB8OO,O,4OOO : Close#1
  814.  
  815. SUBROUTINE: FileToVar FileNum%,Variable,VariableSize%
  816. Copies the specified number of bytes (VariableSize%) from a file (at the current
  817. file pointer location) directly into memory at the location of the specified
  818. Variable.  The FileNum% is BASIC's file number (not the file handle).  The file
  819. must already be opened in Binary Access Read mode. This routine is handy for
  820. reading from a file directly into a TYPE variable.
  821. ex: TYPE NewVar:First as Integer:Second as Integer:END TYPE:Dim Temp as NewVar
  822.     Open "Temp.TMP" for Binary Access Read as #1
  823.     FileToVar 1,Temp.First,4 : Close#1  'reads both 2-byte integers
  824.  
  825. FUNCTION: FindFile$ (First%,Search$,AttrMask%)
  826. Returns a 34-byte directory string containing information about the file(s)
  827. specified in the Search$ string.  The First% operand must be zero (O) for the
  828. first function call to this routine and non-zero for all subsequent calls
  829. (with the same Search$ and AttrMask% specification).  If a different search
  830. criteria specification is given (later in the program) then First% must again
  831. be set to zero for the first call and non-zero for subsequent calls.  This is
  832. due to the fact that the DOS call used here must set up the DTA area on the
  833. first call.  Additional calls, using a non-zero First% value, will use the DTA
  834. area previously defined.  The Search$ operand can be any valid file
  835. specification including directory names, wildcards etc.  Please note that the
  836. 11-byte filename RETURNED by this function will NOT include its directory name.
  837. The AttrMask% tells DOS which types of files to include in the search.  Normal
  838. files (non-directory, non-volume label, non-hidden etc.) are ALWAYS included
  839. except when bit 3 (binary value 8) is set.  See the example for bit meanings.
  840. The 34-byte FindFile$ string returned by this function has the following form:
  841.            
  842. ┌─filename in FILENAMEEXT form (no path/directory name returned for the file)
  843. │          ┌─filesize in 1O-byte string form
  844. │          │         ┌─file date in YYYYMMDD form (YYYY=year MM=month DD=day)
  845. │          │         │       ┌─file time in HHMM (24hr) form
  846. ├─────────┐├────────┐├──────┐├──┐┌─file attribute byte
  847. FILENAMEEXT2147483647199912312359#
  848.  
  849. FindFile$ returns a null ("") string when no more files are found.
  850.  
  851. Note: The filesize is returned as a 1O-byte string.  It was possible to return
  852.       a 4-byte (compressed) value thus saving 6 bytes, however most programmers
  853.       would want to print this field directly or use it in a sort routine,
  854.       therefore it was decided to put it in printable form in the return string.
  855.       The FindFileS subroutine (on the next page) is a shortened version of
  856.       this routine.
  857.  
  858. Example: Find first file matching *.* specification
  859.  
  860. F$=FindFile$(O,"*.*",7)
  861. FileName$=Left$(F$,8)+"."+Mid$(F$,9,3)
  862.     'FileName$ converts FILENAMEEXT form to FILENAME.EXT form
  863. FSize$=Mid$(F$,12,1O)
  864.     'FSize$ is the file size in 1O-byte string form (handy for sorting/printing)
  865.     'could also use FSize$=Right$(Mid$(F$,12,1O),NumDigits%) to shorten string
  866. FDate$=Mid$(F$,26,2)+"-"+Mid$(F$,28,2)+"-"+Mid$(F$,22,4)
  867.     'FDate$ converts YYYYMMDD form to MM-DD-YYYY form
  868. Time24$=Mid$(F$,3O,2)+":"+Mid$(F$,32,2)
  869.     'Time24$ converts HHMM to HH:MM (24hr) form
  870. FAttr%=AscMid%(F$,34)
  871.     'FAttr% uses GPS library function AscMid% to get the file attribute byte:
  872.     'bit O binary value 1 = read-only
  873.          1              2 = hidden
  874.          2              4 = system
  875.          3              8 = volume ID
  876.          4             16 = directory
  877.  
  878. SUBROUTINE: FindFileS First%,Search$,AttrMask%,TypeVariable
  879. This subroutine is identical to the FindFile function except that a shorter
  880. (2O-byte) string is returned INTO the specified TypeVariable.  This shorter
  881. string is useful if a large list of files (and file info) is to be stored in
  882. memory. The following program code shows how to define and use the TypeVariable.
  883. This routine requires more work in uncompressing the DTA-format-information
  884. than the FindFile function does.
  885.  
  886. Type DirVar 
  887.      FileName as String*8
  888.      FileExt as String*3
  889.      Attribute as String*1
  890.      FTime as Integer
  891.      FDate as Integer
  892.      FSize as Long
  893. End Type
  894. Dim Dir as DirVar
  895.  
  896. '---Dir is now a variable of Type DirVar
  897.  
  898. FindFileS  O,"*.*",7,Dir   'for first try use First%=O
  899. FindFileS -1,"*.*",7,Dir   'for subsequent tries use non-zero First%
  900. The Dir.Attribute is set to ASCII 255 when no more files are found.
  901.  
  902. 'after the FindFileS subroutine is executed, the following variables
  903. 'are available for use in your program:
  904.  
  905. 'Dir.FileName is the filename as an 8-byte fixed-length string
  906. 'Dir.FileExt  is the extension as a 3-byte fixed-length string
  907.  Name$ = RTRIM$(Dir.FileName) : Ext$  = RTRIM$(Dir.FileExt)
  908.  If Ext$<>"" Then Name$=Name$+"."+Ext$
  909.  
  910. 'Dir.Attribute is a 1-byte fixed-length string representing the file's attribute
  911. '              byte (use BASIC's ASC function to get its integer value)
  912.                FileAttr% = ASC(Dir.Attribute)
  913.  
  914. 'Dir.FTime is the file time as a 16-bit integer (DTA format)
  915. '          Note: Dir.Time is a SIGNED integer - be careful when sorting by time
  916. '          x   x   x   x   x   x   x   x   x   x   x   x   x   x   x   x   
  917. '         └─┬───────────────┘ └───┬─────────────────┘ └──┬──────────────┘
  918. '         Hours (O to 23)     Minutes (O to 59)       Seconds in 2sec intervals
  919.           FileTime% = Dir.FTime
  920.           '---or---
  921.           FileTime% = ShiftRight%(Dir.FTime,5) 'to use in sort routines
  922.  
  923. 'Dir.FDate is the file date as a 16-bit integer (DTA format)
  924. '          x   x   x   x   x   x   x   x   x   x   x   x   x   x   x   x
  925. '         └─┬───────────────────────┘ └─┬───────────┘ └─┬───────────────┘
  926. '         Year - 198O (offset)        Month (1 to 12)  Day (1 to 31)
  927.           FileDate% = Dir.FDate
  928.  
  929. 'Dir.FSize is the file size as a 4-byte (long) integer
  930.            FileSize& = Dir.FSize
  931.  
  932. SUBROUTINE: MemToFile FileNum%,MemSeg%,MemAdr%,NumBytes%
  933. Copies the specified number of bytes (NumBytes%) from memory at paragraph
  934. (MemSeg%) and offset (MemAdr%) into the file (at the current file pointer
  935. location) whose BASIC file number (FileNum%) is specified.  The file must
  936. already be opened in Binary mode.  Note: The BASIC file number is not the
  937. same thing as the DOS file handle number.
  938. example:
  939. 'Copy 4OOO bytes from video memory to a file
  940. Open "Temp.SCN" for Output as #1 : Close#1 'this resets filesize to O if needed
  941. Open "Temp.SCN" for Binary as #1
  942. MemToFile 1,&HB8OO,O,4OOO : Close#1
  943.  
  944. FUNCTION: StartUpDir$
  945. Returns the directory containing the currently running .EXE file.  This is
  946. handy for accessing data files associated with the current program.  Note
  947. that the directory ALWAYS ends with a backslash (\).  This allows easy
  948. concatenation of filenames to the directory name.  If you need to perform a
  949. CHDIR to the start up directory then you must remove the (\) from the directory
  950. names other than the root directory.
  951. example: SDir$=StartUpDir$
  952.         'SDir$ would have the general form C:\ (root directory) or C:\TEMP\MISC\
  953.          DataFile$=SDir$+"Temp.Dat"
  954.          If LEN(SDir$)=3 then CHDIR SDir$ else CHDIR LEFT$(SDir$,LEN(SDir$)-1)
  955.  
  956. FUNCTION: StartUpExec$
  957. Returns the name of the currently running .EXE executable file.  This can be
  958. used to access data which has been added to the end of an .EXE file.
  959. e.g. COPY/B TEMP.EXE+DATA.FIL PROGRAM.EXE
  960. example: SExec$=StartUpExec$
  961.          Open SExec$ for Input as #2
  962.          Seek#2,EXEFileSize&+1 'EXE filesize (without added data) must be known
  963.          '....retrieve data here....
  964.  
  965. SUBROUTINE: VarToFile FileNum%,Variable,VariableSize%
  966. Copies the specified number of bytes (VariableSize%) from memory at
  967. the location of the Variable into the file (at the current file pointer
  968. location) whose BASIC file number (FileNum%) is specified.  The file must
  969. already be opened in Binary mode.  Note: The BASIC file number is not the
  970. same thing as the DOS file handle number. This routine is handy for writing
  971. from a TYPE variable directly into a file.
  972. ex: TYPE NewVar:First as Integer:Second as Integer:END TYPE:Dim Temp as NewVar
  973.     Open "Temp.SCN" for Output as #1 : Close#1 'resets filesize to O if needed
  974.     Open "Temp.TMP" for Binary Access as #1
  975.     VarToFile 1,Temp.First,4 : Close#1  'writes both 2-byte integers
  976.  
  977. ┌─────────────────────────────────────────────────────────────────────────────┐
  978. │         JOYSTICK FUNCTIONS                                                  │
  979. └─────────────────────────────────────────────────────────────────────────────┘
  980. FUNCTION: JoyStkAX%
  981. Returns the X (horizontal) value of Joystick A.
  982. example: JAX%=JoyStkAX%
  983.  
  984. FUNCTION: JoyStkAY%
  985. Returns the Y (vertical) value of Joystick A.
  986. example: JAY%=JoyStkAY%
  987.  
  988. FUNCTION: JoyStkAFire%
  989. Returns -1 if the fire (top) button on Joystick A is pressed, otherwise it
  990. returns O.
  991. example: JAF%=JoyStkAFire%
  992.  
  993. FUNCTION: JoyStkABase%
  994. Returns -1 if the base (bottom) button on Joystick A is pressed, otherwise it
  995. returns O.
  996. example: JAB%=JoyStkABase%
  997.  
  998. FUNCTION: JoyStkBX%
  999. Returns the X (horizontal) value of Joystick B.
  1000. example: JBX%=JoyStkBX%
  1001.  
  1002. FUNCTION: JoyStkBY%
  1003. Returns the Y (vertical) value of Joystick B.
  1004. example: JBY%=JoyStkBY%
  1005.  
  1006. FUNCTION: JoyStkBFire%
  1007. Returns -1 if the fire (top) button on Joystick B is pressed, otherwise it
  1008. returns O.
  1009. example: JBF%=JoyStkBFire%
  1010.  
  1011. FUNCTION: JoyStkBBase%
  1012. Returns -1 if the base (bottom) button on Joystick B is pressed, otherwise it
  1013. returns O.
  1014. example: JBB%=JoyStkBBase%
  1015.  
  1016. ┌─────────────────────────────────────────────────────────────────────────────┐
  1017. │         KEYBOARD FUNCTIONS                                                  │
  1018. └─────────────────────────────────────────────────────────────────────────────┘
  1019. FUNCTION: CapsLock%
  1020. Returns -1 if the Caps-Lock state is ON, otherwise returns O.
  1021. example: X%=CapsLock%
  1022.  
  1023. SUBROUTINE: CapsLockOn
  1024. Turns ON the Caps-Lock state.
  1025. example: CapsLockOn
  1026.  --or--  Call CapsLockOn
  1027.  
  1028. SUBROUTINE: CapsLockOff
  1029. Turns OFF the Caps-Lock state.
  1030. example: CapsLockOff
  1031.  --or--  Call CapsLockOff
  1032.  
  1033. FUNCTION: GetKey%
  1034. Returns the keycode of the last key pressed (see the keycode table in the
  1035. appendix).  Returns zero (O) if no key was pressed.  This function does NOT
  1036. wait for a keypress.  Note: GetKey% reads STDIN and thus can be redirected.
  1037. example: Do : K%=GetKey% : Loop While K%=O
  1038.  
  1039. FUNCTION: KeyAlt%
  1040. Returns -1 if either Alt key is pressed, otherwise returns O.
  1041. example: X%=KeyAlt%
  1042.  
  1043. FUNCTION: KeyLAlt%
  1044. Returns -1 if the Left Alt key is pressed, otherwise returns O.
  1045. example: X%=KeyLAlt%
  1046.  
  1047. FUNCTION: KeyRAlt%
  1048. Returns -1 if the Right Alt key is pressed, otherwise returns O.
  1049. example: X%=KeyRAlt%
  1050.  
  1051. FUNCTION: KeyCtrl%
  1052. Returns -1 if either Ctrl key is pressed, otherwise returns O.
  1053. example: X%=KeyCtrl%
  1054.  
  1055. FUNCTION: KeyLCtrl%
  1056. Returns -1 if the Left Ctrl key is pressed, otherwise returns O.
  1057. example: X%=KeyLCtrl%
  1058.  
  1059. FUNCTION: KeyRCtrl%
  1060. Returns -1 if the Right Ctrl key is pressed, otherwise returns O.
  1061. example: X%=KeyRCtrl%
  1062.  
  1063. FUNCTION: KeyPending%
  1064. Returns -1 if there is a keycode pending in the keyboard buffer, otherwise
  1065. returns O.  This function does NOT retrieve the keycode.  It simply signals
  1066. that a key has been pressed.
  1067. example: While Not KeyPending% : Wend  'loop until a key is pressed
  1068.          K%=GetKey%                    'get the keycode of that key
  1069.  
  1070. FUNCTION: KeyShift%
  1071. Returns -1 if either Shift key is pressed, otherwise returns O.
  1072. example: X%=KeyShift%
  1073.  
  1074. FUNCTION: KeyLShift%
  1075. Returns -1 if the Left Shift key is pressed, otherwise returns O.
  1076. example: X%=KeyLShift%
  1077.  
  1078. FUNCTION: KeyRShift%
  1079. Returns -1 if the Right Shift key is pressed, otherwise returns O.
  1080. example: X%=KeyRShift%
  1081.  
  1082. FUNCTION: NumLock%
  1083. Returns -1 if the Num-Lock state is ON, otherwise returns O.
  1084. example: X%=NumLock%
  1085.  
  1086. SUBROUTINE: NumLockOn
  1087. Turns ON the Num-Lock state.
  1088. example: NumLockOn
  1089.  --or--  Call NumLockOn
  1090.  
  1091. SUBROUTINE: NumLockOff
  1092. Turns OFF the Num-Lock state.
  1093. example: NumLockOff
  1094.  --or--  Call NumLockOff
  1095.  
  1096. SUBROUTINE: PressAnyKey
  1097. Pauses until a key is pressed.  No prompt is displayed and no value is returned.
  1098. example: PressAnyKey
  1099.  --or--  Call PressAnyKey
  1100.  
  1101. FUNCTION: ScrollLock%
  1102. Returns -1 if the Scroll-Lock state is ON, otherwise returns O.
  1103. example: X%=ScrollLock%
  1104.  
  1105. SUBROUTINE: ScrollLockOn
  1106. Turns ON the Scroll-Lock state.
  1107. example: ScrollLockOn
  1108.  --or--  Call ScrollLockOn
  1109.  
  1110. SUBROUTINE: ScrollLockOff
  1111. Turns OFF the Scroll-Lock state.
  1112. example: ScrollLockOff
  1113.  --or--  Call ScrollLockOff
  1114.  
  1115. SUBROUTINE: SetTypematic Rate%, Delay%
  1116. Sets the keyboard typematic rate and delay on PC-AT class machines only.  Will
  1117. not work on PC-XT machines.  Note: cps is characters-per-second.
  1118. ┌─────┬────╥─────┬────╥─────┬────╥─────┬────┐      ┌──────┬────┐
  1119. │Rate%│ cps║Rate%│ cps║Rate%│ cps║Rate%│ cps│      │Delay%│msec│
  1120. ├─────┼────╫─────┼────╫─────┼────╫─────┼────┤      ├──────┼────┤
  1121. │  O  │3O.O║   8 │15.O║  16 │ 7.5║  24 │ 3.7│      │   O  │ 25O│
  1122. │  1  │26.7║   9 │13.3║  17 │ 6.7║  25 │ 3.3│      │   1  │ 5OO│
  1123. │  2  │24.O║  1O │12.O║  18 │ 6.O║  26 │ 3.O│      │   2  │ 75O│
  1124. │  3  │21.8║  11 │1O.9║  19 │ 5.5║  27 │ 2.7│      │   3  │1OOO│
  1125. │  4  │2O.O║  12 │1O.O║  2O │ 5.O║  28 │ 2.5│      └──────┴────┘
  1126. │  5  │18.5║  13 │ 9.2║  21 │ 4.6║  29 │ 2.3│
  1127. │  6  │17.1║  14 │ 8.6║  22 │ 4.3║  3O │ 2.1│
  1128. │  7  │16.O║  15 │ 8.O║  23 │ 4.O║  31 │ 2.O│
  1129. └─────┴────╨─────┴────╨─────┴────╨─────┴────┘
  1130. example: SetTypematic 8,1 'set 15 cps rate and 5OO msec delay
  1131.  
  1132. SUBROUTINE: TypeAhead Text$
  1133. Places the Text$ string into the keyboard buffer as if the user had typed
  1134. it from the keyboard.  If an extended key sequence is desired (such as F3),
  1135. place a CHR$(O) into the string followed by the CHR$(scan-code) of that key.
  1136. Scan codes are listed in the appendix.  Note that the maximum number of
  1137. keystrokes which can be placed into the keyboard buffer is 15.
  1138. example: TypeAhead "DIR"+CHR$(13)  'DIR command followed by the Enter key
  1139.  
  1140. FUNCTION: WaitKey%
  1141. Returns the keycode of the last key pressed (see the keycode table in the
  1142. appendix).  This function WAITS for a keypress.  Note: WaitKey% reads STDIN
  1143. and thus can be redirected.
  1144. example: K%=WaitKey%
  1145.  
  1146. SUBROUTINE: WaitSpecKey SpecKey%
  1147. Pauses the program until the user presses the specified key. (see the keycode
  1148. table in the appendix).  Note: WaitSpecKey reads STDIN and thus can be
  1149. redirected.
  1150. example: WaitSpecKey 27 'would wait for the Escape key to be pressed
  1151.  
  1152. ┌─────────────────────────────────────────────────────────────────────────────┐
  1153. │         MEMORY FUNCTIONS                                                    │
  1154. └─────────────────────────────────────────────────────────────────────────────┘
  1155. FUNCTION:   BitGet% (ArraySeg%, Element%)
  1156. SUBROUTINE: BitSet ArraySeg%, Element%, Value%
  1157. These routines will allow the programmer to make use of a BIT array.  The
  1158. BitGet% function returns a value of O or -1 based upon the setting of a single
  1159. bit in the memory block which starts at paragraph (ArraySeg%) and offset zero.
  1160. Note that the memory block must start on an even paragraph boundary.  The
  1161. SETMEM and GetMem routines can be used to allocate sufficient memory space for
  1162. the bit array. The Element% operand (O to Max Element) specifies which bit is
  1163. to be accessed.  BitSet sets the bit array element to Value% (O or 1 (-1 can
  1164. also be used)).  For example, suppose a 4O35 element bit array is to be used.
  1165. Note that the elements (i.e. array subscripts) would range from O to 4O34.
  1166. A%=SETMEM(-537) '4O35 bits / 8 bits-per-byte = 5O4.375 bytes so use 5O5 bytes
  1167.                 '(always round UP)
  1168.                 'tell Quick-BASIC's far heap manager to release 5O5 bytes
  1169.                 '(plus extra 32 bytes allows for rounding in the next step)
  1170. ASeg%=GetMem%(32) 'specify the number of PARAGRAPHS (1 paragraph=16 bytes)
  1171.                    '5O5 bytes / 16 bytes-per-paragraph = 31.5625 paragraphs
  1172.                    'round UP to 32 paragraphs 
  1173.                    'because DOS allocates memory in 16-byte blocks
  1174. BitSet ASeg%,999,O    'sets element 999 to zero
  1175. B%=BitGet%(ASeg%,999) 'B% would be zero
  1176. BitSet ASeg%,999,1    'sets element 999 to one (note:BitSet ASeg%,999,-1 ok too)
  1177. B%=BitGet%(ASeg%,999) 'B% would be -1
  1178.  
  1179. FUNCTION: DefSeg%
  1180. Returns the segment used in the last DEF SEG statement.  If DEF SEG has not 
  1181. yet been called, this function returns BASIC's default data segment which is
  1182. called DGROUP.  For example:
  1183. DEF SEG = O     'set a new segment (for use with PEEK/POKE statements)
  1184. NewSeg%=DefSeg% 'the variable NewSeg% now contains zero
  1185.  
  1186. SUBROUTINE: Encrypt MemSegment%,MemPointer%,NumberOfBytes%,XORByteValue%
  1187. This routine performs a simple encryption procedure on the specified memory
  1188. area. To unencrypt, just use the Encrypt routine a second time. It is a bit
  1189. more thorough than the MemXORByte routine. Special note: The memory blocks
  1190. must be the same size and the XORByteValue% must be the same when encrypting
  1191. and unencrypting.
  1192. -example for encrypting a block of memory, copying it, then unencrypting it:
  1193.  Encrypt MemSeg1%,MemOfs1%,NumBytes%,123
  1194.  'memory block is encrypted before it is copied
  1195.  MemCopy MemSeg1%,MemSeg1%,MemSeg2%,MemOfs2%,NumBytes%)
  1196.  'memory block, which has been encrypted, is copied to the destination location
  1197.  Encrypt MemSeg2%,MemOfs2%,NumBytes%,123
  1198.  'memory block is unencrypted at the destination location (after being copied)
  1199. -example for encrypting/unencrypting a string:
  1200.  Encrypt VARSEG(Text$),SADD(Text$),LEN(Text$),255 'string is now encrypted
  1201.  Encrypt VARSEG(Text$),SADD(Text$),LEN(Text$),255 'string is now unencrypted
  1202.  
  1203. FUNCTION: EnvironSeg%
  1204. Returns the memory segment containing the environment belonging to the currently
  1205. running .EXE program.
  1206. example: ESeg% = EnvironSeg%
  1207.          DEF SEG = ESeg%   'you can now use PEEK to look for COMSPEC etc. 
  1208.  
  1209. FUNCTION: GetMem% (NumPara%)
  1210. FUNCTION: RelMem% (SegAdr%)
  1211. The GetMem% function is used to allocate a block of memory which has a size
  1212. (in 16-byte paragraphs) of NumPara%.  Note that DOS allocates memory in 16-byte
  1213. blocks called paragraphs.  The RelMem% function releases (to DOS) the memory
  1214. arena located at paragraph SegAdr%.  GetMem% returns zero (O) if DOS cannot
  1215. find enough memory to satisfy the request, otherwise GetMem% returns the
  1216. paragraph (segment) at which the allocated memory block starts.  Note that
  1217. allocated memory blocks always start on a paragraph boundary (i.e. para:OOOO
  1218. (offset of zero)).  Your program MUST use SETMEM to tell Quick-BASIC's far heap
  1219. manager that it must relinquish control of a block of memory.  For example:
  1220. A%=SETMEM(-(16384&+32&)) 'ask BASIC to release 16k of memory so DOS can have it
  1221.                          '(+32 bytes as a precaution for rounding)
  1222. Segm%=GetMem%(1O24)   'ask DOS for 16k of memory
  1223.                       '(1O24 paragraphs x 16 bytes-per-paragraph = 16384 bytes)
  1224. '..use the 16k-byte block of memory starting at Segm%:OOOO for any purpose...
  1225. ErCode%=RelMem%(Segm%) 'release the block of memory back to DOS
  1226. A%=SETMEM(16384&+32&)    'tell BASIC to reclaim 16k block from DOS
  1227. 'note: all allocated memory is automatically returned to DOS when your
  1228. 'program ends - so that the last two lines of program code are optional
  1229.  
  1230. FUNCTION: LowMem% (MemAdr%)
  1231. Returns the value of the BYTE located in low memory (paragraph (segment) zero
  1232. and offset MemAdr%).  "The Programmer's PC Sourcebook" from MicroSoft Press has
  1233. a table showing the information that is stored in low memory.
  1234. For example,
  1235. A%=LowMem%(&H46C) 'get the byte at location OOOO:O46C (hexadecimal address)
  1236.  
  1237. FUNCTION: MemChkSum& (MemSeg%, MemPtr%, NumBytes%)
  1238. Returns a long integer value representing the sum of all the bytes in the
  1239. memory block (located at MemSeg%:MemPtr% and having a length of NumBytes%).
  1240. example: A&=MemChkSum&(&hB8OO,O,4OOO) 'get check sum of color text screen memory
  1241.  
  1242. FUNCTION: MemCompare% (Seg1%,Adr1%,Seg2%,Adr2%,Bytes%)
  1243. Compares the contents of two memory blocks to determine if they contain
  1244. exactly the same data.  The function returns -1 if the blocks are the same,
  1245. otherwise it returns zero.  The first memory block is located at address
  1246. Seg1%:Adr1% (segment:offset), while the second memory block is located at
  1247. address Seg2%:Adr2% (segment:offset).  The Bytes% operand is used to specify
  1248. the number of bytes, from each block, that are to be compared.  Note: Refer to
  1249. the section on segmented memory at the beginning of this documentation.
  1250. example: A%=MemCompare%(&H1234,&H5678,&H9876,&H5432,128) 'addresses are in hex
  1251. 'compare 128 bytes of the memory blocks starting at 1234:5678 and 9876:5432
  1252. 'A=-1 if the two memory blocks are the same, otherwise A%=O 
  1253.  
  1254. SUBROUTINE: MemCopy Seg1%,Adr1%,Seg2%,Adr2%,Bytes%
  1255. Copies the memory block starting at Seg1%:Adr1% to the memory block starting at
  1256. Seg2%:Adr2%.  The Bytes% operand specifies the number of bytes to copy.
  1257. example:
  1258. MemCopy &hB8OO,O,&h7654,&h321O,4OOO
  1259. 'copies 4OOO bytes from memory block B8OO:OOOO to memory block 7654:321O (hex)
  1260.  
  1261. SUBROUTINE: MemFillByte MemSeg%,MemPtr%,NumBytes%,FillValue%
  1262. Fills the memory block, that starts at MemSeg%:MemPtr% and has a length of
  1263. NumBytes%, with the specified FillValue% byte.
  1264. example: MemFillByte &hB8OO,O,4OOO,32 'fill color screen with black/green spaces
  1265.  
  1266. SUBROUTINE: MemFillWord MemSeg%,MemPtr%,NumWords%,FillValue%
  1267. Fills the memory block, that starts at MemSeg%:MemPtr% and has a length of
  1268. (NumWords% * 2) bytes, with the specified FillValue% word.
  1269. example: MemFill &hB8OO,O,2OOO,8224 'fill color screen with black/green spaces
  1270.  
  1271. SUBROUTINE: MemSwap Seg1%,Adr1%,Seg2%,Adr2%,Bytes%
  1272. Swaps the contents of two memory blocks.  The first memory block is located at
  1273. address Seg1%:Adr1% (segment:offset), while the second memory block is located
  1274. at address Seg2%:Adr2% (segment:offset).  The Bytes% operand is used to specify
  1275. the number of bytes, from each block, that are to be swapped.
  1276.  
  1277. SUBROUTINE: MemXORByte MemSeg%,MemPtr%,NumBytes%,XORByteVal%
  1278. Exclusive-ORs each byte in the memory block, located at address MemSeg%:MemPtr%
  1279. and having a length of NumBytes%, with the XORByteVal%.  This routine could be
  1280. used to make a simple encrypt/decrypt function for a block of memory.
  1281. example: MemXORByte &hB8OO,O,4OOO,255
  1282.  
  1283. SUBROUTINE: MemXORWord MemSeg%,MemPtr%,NumWords%,XORWordVal%
  1284. Exclusive-ORs each word in the memory block, located at address MemSeg%:MemPtr%
  1285. and having a length in bytes of (NumWords% * 2), with the XORWordVal%.  This
  1286. routine can be used to make an encrypt/decrypt function for a block of memory.
  1287. example: MemXORWord &hB8OO,O,2OOO,&hFFOO 'each word is 2 bytes in length
  1288.  
  1289. SUBROUTINE: MinimizePtr OldSeg%,OldPtr%,NewSeg%,NewPtr%
  1290. Reduces the size of the pointer (offset) of the given segmented address.  The
  1291. original address is given as OldSeg%:OldPtr% while the resultant (minimized
  1292. pointer) address is given as NewSeg%:NewPtr%.  This function forces the NewPtr%
  1293. variable to have a value in the range of O to 15.  It is useful to minimize an
  1294. address prior to using MemCopy, MemCompare etc. because an SI or DI register
  1295. overflow can occur if the offset (pointer) plus the number of bytes to
  1296. move/compare etc. exceeds 65535 (FFFF hex).
  1297.  
  1298. FUNCTION: PeekByte%  (MemSeg%, MemAdr%)
  1299. Returns the value of a single byte in memory at address MemSeg%:MemAdr%.
  1300. Unlike BASIC's PEEK command, this function allows the user to specify the
  1301. memory segment to use.  This means that the DEF SEG command does not have to
  1302. be used prior to peeking at the memory location.  For example,
  1303. A%=PeekByte%(&hB8OO,&h1234) 'A% is set equal to the byte at B8OO:1234 (hex)
  1304.  
  1305. FUNCTION: PeekWord%  (MemSeg%, MemAdr%)
  1306. Returns the value of a 2-byte word in memory starting at address
  1307. MemSeg%:MemAdr%.  Note that two successive bytes are read by this function 
  1308. in order to build a 2-byte word return value.  For example:
  1309. A%=PeekWord%(&h1234,&h5678)  'is equivalent to:
  1310.                              'DEF SEG = &h1234
  1311.                              'A% = PEEK(&h5678) + ( 256% * PEEK(&h5679) )
  1312.  
  1313. FUNCTION: PeekLong&  (MemSeg%, MemAdr%)
  1314. Returns the value of a 4-byte double word, in memory starting at address
  1315. MemSeg%:MemAdr%, into a long (&) integer.
  1316. Note that four successive bytes are read by this function in order to build a
  1317. 4-byte long integer return value.  For example:
  1318. A&=PeekLong&(O,&h46C) 'reads the PC's timer tick value (4 bytes long)
  1319.  
  1320. SUBROUTINE: PokeByte  MemSeg%, MemAdr%, Value%
  1321. Places the byte Value% into memory at MemSeg%:MemAdr%.  Note that it does not
  1322. require the DEF SEG command that BASIC's POKE statement uses.  For example,
  1323. PokeByte &hB8OO,&hO5OO,32 'puts a space in the color text screen memory area
  1324.  
  1325. SUBROUTINE: PokeWord  MemSeg%, MemAdr%, Value%
  1326. Places the 2-byte integer Value% into two consecutive (byte-wide) memory
  1327. locations starting at MemSeg%:MemAdr%.  For example,
  1328. PokeWord &hB8OO,&hO5OO,83O4 
  1329. 'places 83O4 into memory at B8OO:O5OO (low byte at :O5OO and high byte at :O5O1)
  1330.  
  1331. SUBROUTINE: PokeLong  MemSeg%, MemAdr%, Value&
  1332. Places the 4-byte integer Value& into four consecutive (byte-wide) memory
  1333. locations starting at MemSeg%:MemAdr%.  For example,
  1334. PokeLong &h9876,&h5432,&h12345678 'lowest order byte at lowest address (offset)
  1335. 'places &h78 at 9876:5432 (hex address)
  1336. 'places &h56 at 9876:5433
  1337. 'places &h34 at 9876:5434
  1338. 'places &h12 at 9876:5435
  1339.  
  1340. FUNCTION: PSPSeg%
  1341. Returns the PSP segment of the current process.  The PSP contains pointers
  1342. to the parent process PSP segment (offset 16h) and to the environment segment
  1343. (offset 2Ch).  It also contains the command line parameters (starting at offset
  1344. 81h with the command line parameter length at offset 8Oh).
  1345. For example, get the command line (including the leading space)
  1346. PSeg%=PSPSeg% : DEF SEG=PSeg% : Cmd$="" 
  1347. For I%=1 to PEEK(&h8O):Cmd$=Cmd$+CHR$(PEEK(&h8O+I%)):Next I%
  1348.  
  1349. FUNCTION: ReadCMOS% (CMOSAdr%)
  1350. Returns the value from the specified address (O to 53) in CMOS memory (PC-AT+
  1351. using MC146818A real time clock chip only).  Some important addresses are:
  1352. O=seconds  2=minutes  4=hours  6=day-of-week  7=day  8=month  9=year.  Note
  1353. that many of these values are stored in BCD (binary-coded-decimal) form.
  1354. Suppose the current minute is 59 (normal decimal form).  It is stored in CMOS
  1355. RAM as 59 BCD.  Note that BCD is like hexadecimal without the A through F
  1356. digits.  This means that 59 BCD is actually stored as 59 hex.
  1357. example:
  1358. BCDmin% = ReadCMOS%(2)
  1359. Minutes% = (1O% * ( BCDmin% \ 16% )) + (BCDmin% AND 15%) 'convert BCD to decimal
  1360.  '--or you can use the BCDtoDEC% function--
  1361. Minutes% = BCDtoDEC%(BCDmin%) 'convert BCD to DECimal
  1362.  
  1363. FUNCTION: RelMem% (SegAdr%)
  1364. ** see GetMem function **
  1365.  
  1366. SUBROUTINE: VarSegPtr Variable, SegAdr%, PtrAdr%
  1367. Calculates the 'minimized' segment:offset address of the given Variable (any
  1368. kind) and returns the segment (paragraph) in SegAdr% and returns the offset
  1369. (pointer) in PtrAdr%.  For example,
  1370. VarSegPtr Test%,MemSeg%,MemPtr%
  1371. '---is the same as---
  1372. MSeg%=VARSEG(Test%)
  1373. MAdr%=VARPTR(Test%)
  1374. MinimizePtr MSeg%,MAdr%,MemSeg%,MemPtr%
  1375.  
  1376. SUBROUTINE: WriteCMOS CMOSAdr%, Value%
  1377. Writes the byte Value% to CMOS RAM address CMOSAdr%.  Note that the address
  1378. must be in the range of O to 9 only.  See the ReadCMOS% function for more
  1379. details. For example:
  1380. WriteCMOS 2,&h59 'write 59 (in BCD form) to CMOS address 2 (minutes)
  1381. '---or you can use the DECtoBCD% function---
  1382. A%=DECtoBCD%(59%)
  1383. WriteCMOS 2,A% 'write 59 (in BCD form) to CMOS address 2 (minutes)
  1384.  
  1385. ┌─────────────────────────────────────────────────────────────────────────────┐
  1386. │         MOUSE FUNCTIONS                                                     │
  1387. └─────────────────────────────────────────────────────────────────────────────┘
  1388. Note: The MsReset% function MUST be called BEFORE ANY other mouse functions
  1389.       or subroutines can be accessed !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1390.  
  1391. FUNCTION: MsBtn%
  1392. Returns zero if no mouse buttons are being pressed, otherwise it returns a
  1393. composite value using the binary weighting of each mouse button.
  1394. Left Button   = 1
  1395. Right Button  = 2
  1396. Center Button = 4
  1397. example: A%=MsBtn% 'A% would be 7 (1+2+4) if all mouse buttons are being pressed
  1398.  
  1399. FUNCTION: MsCBtn%
  1400. Returns -1 if the center mouse button is being pressed and zero otherwise.
  1401. Note that some earlier versions of the mouse driver do not report the status
  1402. of the center mouse button.
  1403. example: A%=MsCBtn%
  1404.  
  1405. FUNCTION: MsClickCount% (WhichButton%)
  1406. Returns the number of times the specified button has been pressed since the
  1407. last call to this routine.  This is useful in checking for a double-click on a
  1408. menu option etc.  Note that the click-count for the specified button is reset
  1409. to zero after this routine is called.  The WhichButton% operand should be
  1410. O for the left mouse button, 1 for the right button and 2 for the center button.
  1411. example: A%=MsClickCount%(1)
  1412.          'A% will be the number of times that the right mouse button has been
  1413.          'pressed since the last call to this routine
  1414.  
  1415. SUBROUTINE: MsGetCsrPos CsrType%, Row%, Column%
  1416. SUBROUTINE: MsSetCsrPos CsrType%, Row%, Column%
  1417. MsGetCsrPos returns the position of the mouse pointer in the Row%, Column% 
  1418. variables.  In graphics mode, the mouse pointer "hot-spot" position is returned.
  1419. MsSetCsrPos sets the mouse pointer position to the values specified by the
  1420. Row% and Column% variables.
  1421. If CsrType% is O (text mode):
  1422.    Row% will be 1 to 25 (text-mode row)
  1423.    Column% will be 1 to 8O (text-mode column)
  1424. If CsrType% is 1 (graphics mode):
  1425.    Row% will be the vertical position (O to maximum row [in pixels])
  1426.    Column% will be the horizontal position (O to maximum column [in pixels]) 
  1427. Note: Row%=O and Column%=O is the upper-left corner of the graphics mode screen
  1428. example: MsGetCsrPos O,MRow%,MCol%
  1429.          --or--
  1430.          Call MsGetCsrPos(O,MRow%,MCol%)
  1431.         'returns MRow% (row) and MCol% (column) of the text-mode mouse cursor
  1432.         'Note: see the InBox% function to determine if the mouse is in a certain
  1433.         '      area ("box") on the screen
  1434. example: MsSetCsrPos O,13,4O 'set text-mode mouse cursor to row=13 and column=4O
  1435.          --or--
  1436.          Call MsSetCsrPos(O,13,4O)
  1437.  
  1438. SUBROUTINE: MsGetSensPct XMicks%, YMicks%, DblSpdMicks%
  1439. SUBROUTINE: MsSetSensPct XMicks%, YMicks%, DblSpdMicks%
  1440. The MsGetSensPct routine returns a percentage (1 to 1OO) of the maximum 
  1441. mouse sensitivity in the operand variables.  The MsSetSensPct routine sets the
  1442. percentage of maximum mouse sensitivity (1 to 1OO) for the operand variables.
  1443. XMicks% is (1 to 1OO) percent of the maximum horizontal mouse sensitivity which
  1444.         is in mickeys-per-pixel.  Standard mouse=2OO mickeys-per-inch of travel.
  1445. YMicks% is (1 to 1OO) percent of the maximum vertical mouse sensitivity which is
  1446.         in mickeys-per-pixel.
  1447. DblSpdMicks% is (1 to 1OO) percent of the default double speed threshold.  The
  1448.         double speed threshold is the mouse travel speed (which is measured in
  1449.         mickeys-per-second) at which the mouse sensitivity is doubled.
  1450.  
  1451. SUBROUTINE: MsGrPtrShape HotSptLeft%,HotSptTop%,SegPtrBfr%,OfsPtrBfr%
  1452. Defines the shape of the mouse graphics cursor.  In normal graphics modes the
  1453. graphics cursor has a size of 16-by-16 pixels.  The "hot-spot", which is the
  1454. point inside the 16-by-16 block that is reported to the mouse driver as the
  1455. cursor position, is located HotSptLeft% pixels from the left side and HotSptTop%
  1456. pixels from the top of the 16-by-16 graphics cursor block.  The shape of the
  1457. graphics cursor is defined by a block of data which has a segment:offset
  1458. address of SegPtrBfr%:OfsPtrBfr%.  The 64-byte data block consists of a screen
  1459. AND-mask (1 word-by-16) followed by a cursor XOR-mask (1 word-by-16).  A "word"
  1460. is 2 bytes or 16 bits in length so that a 16bit-by-16bit AND mask followed by
  1461. a 16bit-by-16bit XOR mask can be stored in 64 bytes of memory.  For example,
  1462. DIM Csr%(31) 'O to 15 for AND-mask    16 to 31 for XOR-mask
  1463. Csr%(OO)=&hE1FF '111OOOO111111111 ┐
  1464. Csr%(O1)=&hE1FF '111OOOO111111111 │
  1465. Csr%(O2)=&hE1FF '111OOOO111111111 │
  1466. Csr%(O3)=&hE1FF '111OOOO111111111 │
  1467. Csr%(O4)=&hE1FF '111OOOO111111111 │
  1468. Csr%(O5)=&hEOOO '111OOOOOOOOOOOOO │
  1469. Csr%(O6)=&hEOOO '111OOOOOOOOOOOOO │
  1470. Csr%(O7)=&hEOOO '111OOOOOOOOOOOOO ├──── AND-Mask ─┐
  1471. Csr%(O8)=O      'OOOOOOOOOOOOOOOO │     (Screen)  │
  1472. Csr%(O9)=O      'OOOOOOOOOOOOOOOO │               │
  1473. Csr%(1O)=O      'OOOOOOOOOOOOOOOO │               │
  1474. Csr%(11)=O      'OOOOOOOOOOOOOOOO │               │
  1475. Csr%(12)=O      'OOOOOOOOOOOOOOOO │               │
  1476. Csr%(13)=O      'OOOOOOOOOOOOOOOO │               │
  1477. Csr%(14)=O      'OOOOOOOOOOOOOOOO │               │
  1478. Csr%(15)=O      'OOOOOOOOOOOOOOOO ┘               ├─ Notice the shape of a
  1479. Csr%(16)=&h1EOO 'OOO1111OOOOOOOOO ┐               │  hand in both masks
  1480. Csr%(17)=&h12OO 'OOO1OO1OOOOOOOOO │               │
  1481. Csr%(18)=&h12OO 'OOO1OO1OOOOOOOOO │               │
  1482. Csr%(19)=&h12OO 'OOO1OO1OOOOOOOOO │               │
  1483. Csr%(2O)=&h12OO 'OOO1OO1OOOOOOOOO │               │
  1484. Csr%(21)=&h13FF 'OOO1OO1111111111 │               │
  1485. Csr%(22)=&h1249 'OOO1OO1OO1OO1OO1 │               │
  1486. Csr%(23)=&h1249 'OOO1OO1OO1OO1OO1 ├──── XOR-Mask ─┘
  1487. Csr%(24)=&hF249 '1111OO1OO1OO1OO1 │     (Cursor)
  1488. Csr%(25)=&h9OO1 '1OO1OOOOOOOOOOO1 │
  1489. Csr%(26)=&h9OO1 '1OO1OOOOOOOOOOO1 │
  1490. Csr%(27)=&h9OO1 '1OO1OOOOOOOOOOO1 │
  1491. Csr%(28)=&h8OO1 '1OOOOOOOOOOOOOO1 │
  1492. Csr%(29)=&h8OO1 '1OOOOOOOOOOOOOO1 │
  1493. Csr%(3O)=&h8OO1 '1OOOOOOOOOOOOOO1 │
  1494. Csr%(31)=&hFFFF '1111111111111111 ┘
  1495. MsGrPtrShape 5,O,VARSEG(Csr%(O)),VARPTR(Csr%(O)) : MsShow 'needed to show it
  1496.  
  1497. SUBROUTINE: MsHide
  1498. Turns the mouse cursor OFF so that it is not visible on the screen.  Note that
  1499. writing over the area containing the mouse cursor will remove it from the 
  1500. screen.  It is usually best to hide the mouse cursor prior to writing/printing 
  1501. to the screen.  It can be restored (using MsShow) later in the program.
  1502. example: MsHide
  1503.          --or--
  1504.          Call MsHide
  1505.  
  1506. FUNCTION: MsLBtn%
  1507. Returns -1 if the left mouse button is being pressed and zero otherwise.
  1508. example: While Not MsLBtn%
  1509.          Wend  'exit loop when left mouse button is pressed
  1510.  
  1511. FUNCTION: MsRBtn%
  1512. Returns -1 if the right mouse button is being pressed and zero otherwise.
  1513. example: A%=MsRBtn%
  1514.  
  1515. FUNCTION: MsReset%
  1516. Resets the mouse driver and returns the status of the mouse.  This function
  1517. returns -1 if a mouse is present and zero if no mouse was found.  This
  1518. function MUST be called prior to calling any other mouse routines.  Normally
  1519. the mouse should be reset at the beginning (and end) of the program.  Note that
  1520. calling the MsReset% function also hides the mouse cursor.  If your program
  1521. changes the screen mode, MsReset% should be called after the change is made.
  1522.  
  1523. SUBROUTINE: MsSetCsrPos CsrType%, Row%, Column%
  1524. ** see MsGetCsrPos subroutine **
  1525.  
  1526. SUBROUTINE: MsSetLimit CsrType%,MinRow%,MinColumn%,MaxRow%,MaxColumn%
  1527. Restricts mouse movement on the screen to a box defined by the upper-left
  1528. corner (MinRow%,MinColumn%) and the lower-right corner (MaxRow%,MaxColumn%).
  1529. If CsrType% is O (text mode):
  1530.    Rows are 1 to 25 and columns are 1 to 8O for the text-mode screen.
  1531. If CsrType% is 1 (graphics mode):
  1532.    Rows are O to maximum row value (in pixels) and columns are O to maximum
  1533.    column value (in pixels).
  1534. Note: row=O and column=O specifies the upper-left corner of the graphics screen
  1535.  
  1536. SUBROUTINE: MsSetSens XMicks%, YMicks%, DblSpdMicks%
  1537. Sets the mouse sensitivity according the operand values:
  1538. XMicks% is horizontal mouse sensitivity in mickeys-per-pixel.  There are about
  1539. 2OO mickeys-per-inch of mouse movement for a normal (default) mouse.
  1540. YMicks% is vertical mouse sensitivity in mickeys-per-pixel.
  1541. DblSpdMicks% is the double speed threshold and is the mouse speed (measured in
  1542. mickeys-per-second) at which the mouse sensitivity (mickeys-per-pixel) is
  1543. doubled.  If the screen size (rows and columns in pixels) is known, it is 
  1544. possible to set the sensitivity so that a predetermined amount of mouse travel
  1545. will result in a known amount of screen mouse cursor movement.
  1546.  
  1547. SUBROUTINE: MsSetSensPct XMicks%,YMicks%,DblSpdMicks%
  1548. ** see MsGetSensPct subroutine **
  1549.  
  1550. SUBROUTINE: MsShow
  1551. Turns the mouse cursor ON so that it becomes visible on the screen.
  1552. example: MsShow
  1553.          --or--
  1554.          Call MsShow
  1555.  
  1556. SUBROUTINE: MsTxtPtrType SHPtr%, ANDMask%, XORMask%
  1557. Defines the text-mode mouse pointer type.  SHPtr% determines whether to use a
  1558. software or hardware cursor.  Note that the default text-mode pointer works
  1559. fairly well.  You might have to experiment with the AND/XOR mask values if 
  1560. you wish to use this routine.
  1561. If SHPtr% = O (Software Cursor) then:
  1562.    ANDMask% is logically ANDed with the ASCII character and color attribute
  1563.             at the mouse cursor position. (see bit table below)
  1564.    XORMask% is logically XORed with the ASCII character and color attribute
  1565.             at the mouse cursor position. (see bit table below)
  1566.             Bit  O to  7 : ASCII character code
  1567.             Bit  8 to 1O : Foreground color────────┐ see programming section
  1568.             Bit 11       : Intensity (bright if 1) ├─at beginning of document
  1569.             Bit 12 to 14 : Background color        │ for color codes
  1570.             Bit 15       : Blink Bit (blink if 1)──┘
  1571. If SHPtr% = 1 (Hardware Cursor) then:
  1572.    ANDMask% is the starting scan line of the block cursor
  1573.    XORMask% is the ending scan line of the block cursor.
  1574. example: MsTxtPtrType O,&h7FFF,&h77OO
  1575.  
  1576. FUNCTION: MsWaitClick% (ClickMask%)
  1577. Waits until a specified mouse button is pressed.  The ClickMask% is logically
  1578. ANDed with the button press information (see: MsBtn% function) and returns
  1579. with this modified information when:
  1580. [ (button press info) AND (ClickMask%) ] <> zero.
  1581. example: A%=MsWaitClick%(3)
  1582.         'wait for either left or right mouse button
  1583.         'left=1  right=2 ---> 1+2 = 3 = ClickMask%
  1584.         'A%=1 if left button pressed
  1585.         'A%=2 if right button pressed
  1586.         'A%=3 if both buttons pressed
  1587.  
  1588. ┌─────────────────────────────────────────────────────────────────────────────┐
  1589. │         NUMERIC FUNCTIONS                                                   │
  1590. └─────────────────────────────────────────────────────────────────────────────┘
  1591. FUNCTION: BCDtoDEC% (BCDVal%)
  1592. FUNCTION: DECtoBCD% (DECVal%)
  1593. These functions convert numbers between BCD and DECimal forms.  Note that the 
  1594. values must be in the range (OO to 99 BCD) and (O to 99 DECimal).  Numbers
  1595. outside this range will yield unpredictable return values.  These functions
  1596. are very handy when using the ReadCMOS and WriteCMOS functions.
  1597. example: A% = BCDtoDEC%(&h99)  'A% would be 99 decimal
  1598.          A% = DECtoBCD%(99%)   'A% would be &h99 (or 99 BCD)
  1599.  
  1600. FUNCTION: Caps% (AsciiValue%)
  1601. If the AsciiValue% is between 97 and 122 (inclusive), which corresponds to
  1602. ASCII 97="a" and ASCII 122="z", then the return value is (AsciiValue%-32).
  1603. This converts lower-case ASCII integer values into upper-case values.
  1604. example:  X% = Caps%(45)  ' X%=45 (no change - ASCII 45 is not alphabetic)
  1605.           X% = Caps%(98)  ' X%=66 (ASCII 98 = "b" and ASCII 66 = "B")
  1606.           X% = Caps%(GetKey%)  'forces  GetKey% to return all upper-case (caps)
  1607.           X% = Caps%(WaitKey%) 'forces WaitKey% to return all upper-case (caps)
  1608.  
  1609. FUNCTION: ChgBit% (Value%, BitPos%, Operation%)
  1610. Changes the specified bit of Value% at position (BitPos%=O to 15) according to
  1611. the specified operation:
  1612. Operation% =  O  sets the specified bit to O
  1613.            =  1  sets the specified bit to 1
  1614.            = -1  complements the specified bit (logical NOT).
  1615. example: A%=ChgBit%(Test%,12,1)
  1616. 'sets A% equal to Test% except that bit 12 (binary value 4O96) is set to 1.
  1617. 'note: Bit 15 is the most-significant-bit and Bit O is the least-significant-bit
  1618.  
  1619. FUNCTION: HighWord% (LongInt&)
  1620. Returns the high order 2-byte word of the specified long (4-byte) integer value.
  1621. example: A%=HighWord%(&h12345678) 'A% would be &h1234
  1622.                                   'note: same as A%=&h12345678\65536& but
  1623.                                   '      does not use division function
  1624.  
  1625. FUNCTION: InBox% (TestRow%, TestCol%, Row1%, Col1%, Row2%, Col2%)
  1626. Returns -1 if TestRow% is between Row1% and Row2% (inclusive) and if TestCol% is
  1627. between Col1% and Col2% (inclusive).  It returns zero otherwise.  This function
  1628. was designed primarily to determine if a given row and column (e.g. mouse
  1629. cursor coordinates) are within a given "box" on the screen, where Row1%,Col1%
  1630. is the upper-left corner and Row2%,Col2% is the lower-right corner of the "box".
  1631. This is not the only use for this function.  Note that this function uses SIGNED
  1632. integer values (-32768 to 32767) unlike many of the other functions.
  1633. example: If InBox%(Row%,Col%,1,1,25,8O) then print "ON SCREEN"
  1634.  
  1635. FUNCTION: InRange% (TestVal%, LowVal%, HighVal%)
  1636. Returns -1 if TestVal% is between LowVal% and HighVal% (inclusive).  It returns
  1637. zero otherwise.  Note that this function uses SIGNED integer values (-32768 to
  1638. 32767) unlike many of the other functions.
  1639. example: If InRange%(Test%,1,1OO) then print "IN RANGE"
  1640.          '----is the same as----
  1641.          If (Test% >= 1) AND (Test% <=1OO) then print "IN RANGE"
  1642.  
  1643. FUNCTION: Larger% ( Value1% , Value2% )
  1644. Returns the larger of the two SIGNED integers.  (-32768 to 32767)
  1645. example: A%=Larger%(-1OO,1OO)  'A% would be 1OO
  1646.  
  1647. FUNCTION: LargerL& ( Value1& , Value2& )
  1648. Returns the larger of the two SIGNED long (4-byte) integers.
  1649. example: A&=LargerL&(-1OOOOO,1OOOOO)  'A& would be 1OOOOO
  1650.  
  1651. FUNCTION: LowWord%  (LongInt&)
  1652. Returns the low order 2-byte word of the specified long (4-byte) integer value.
  1653. example: A%=LowWord%(&h12345678) 'A% would be &h5678
  1654.                                  'note: same as A%=(&h12345678 AND 65535&)
  1655.  
  1656. FUNCTION: NoCaps% (AsciiValue%)
  1657. If the AsciiValue% is between 65 and 9O (inclusive), which corresponds to
  1658. ASCII 65="A" and ASCII 9O="Z", then the return value is (AsciiValue%+32).
  1659. This converts upper-case ASCII integer values into lower-case values.
  1660. example: X% = NoCaps%(45)  ' X%=45 (no change - ASCII 45 is not alphabetic)
  1661.          X% = NoCaps%(66)  ' X%=98 ( ASCII 66 = "B" and ASCII 98 = "b" )
  1662.          X% = NoCaps%(GetKey%)  'forces  GetKey% to return lower-case (no caps)
  1663.          X% = NoCaps%(WaitKey%) 'forces WaitKey% to return lower-case (no caps)
  1664.  
  1665. FUNCTION: PowerOf2% (Power%)
  1666. Returns a value equal to: 2 raised to a Power% (O to 15).
  1667. example: A%=PowerOf2%(1O) 'A% would be 2^1O = 1O24.
  1668.  
  1669. FUNCTION: RandNum% (MaxNum%)
  1670. Returns a random integer between zero and MaxNum%.  This function automatically
  1671. seeds the random number generator with the timer tick value when it is called
  1672. for the first time in a program.
  1673. example: A%=RandNum%(5O) 'A% will be between O and 5O (inclusive).
  1674.  
  1675. SUBROUTINE: SetInBox Row%, Column%, Row1%, Column1%, Row2%, Column2%
  1676. If the Row%,Column% values are outside of the "box" (formed by Row1%,Column1%
  1677. as the upper-left corner and Row2%,Column2% as the lower-right corner) then
  1678. the values of Row% and/or Column% are automatically adjusted so that they are
  1679. within the confines of the "box".  Note that this function uses SIGNED integer
  1680. values (-32768 to 32767) unlike many of the other functions.  For example:
  1681. SetInBox Row%,Col%,1,1,25,8O 'make sure that Row%,Col% are on the screen
  1682.  
  1683. SUBROUTINE: SetInRange TestVal%, LowVal%, HighVal%
  1684. If TestVal% is less than LowVal% then TestVal% is set equal to LowVal%.  If
  1685. TestVal% is greater than HighVal% then TestVal% is set equal to HighVal%.
  1686.  Note that this function uses SIGNED integer values (-32768 to 32767) unlike
  1687. many of the other functions.
  1688. example: SetInRange Test%,1,1OO 'make sure Test% is inside the range of 1 to 1OO
  1689.          '----is the same as----
  1690.          If (Test% < 1)   Then Test%=1
  1691.          If (Test% > 1OO) Then Test%=1OO
  1692.  
  1693. FUNCTION: ShiftLeft%  (Value%, NumBits%)
  1694. Returns the Value% shifted (bitwise) to the left by the specified number of
  1695. bits (NumBits%).  Each bit position that the number is shifted is equivalent 
  1696. to multiplying by 2.  Bits shifted past bit 15 are discarded.
  1697. example: A%=ShiftLeft%(12,3) 'A% would be 96 = (12 x (2^3))
  1698. Note: This function assumes Value% is UNsigned (O to 65535).
  1699.  
  1700. FUNCTION: ShiftRight% (Value%, NumBits%)
  1701. Returns the Value% shifted (bitwise) to the right by the specified number of
  1702. bits (NumBits%).  Each bit position that the number is shifted is equivalent 
  1703. to dividing by 2.  Bits shifted past bit O are discarded.
  1704. example: A%=ShiftRight%(192,6) 'A% would be 3 = (192 \ (2^6))
  1705. Note: This function assumes Value% is UNsigned (O to 65535).
  1706.  
  1707. FUNCTION: Smaller% ( Value1% , Value2% )
  1708. Returns the smaller of the two SIGNED integers. (-32768 to 32767)
  1709. example: A%=Smaller%(-1OO,1OO) 'A% would be -1OO
  1710.  
  1711. FUNCTION: SmallerL& ( Value1& , Value2& )
  1712. Returns the smaller of the two SIGNED long (4-byte) integers.
  1713. example: A&=SmallerL&(-1OOOOO,1OOOOO) 'A& would be -1OOOOO
  1714.  
  1715. FUNCTION: SwapBytes%  (Value%)
  1716. Swaps the upper and lower bytes of the 2-byte integer Value%.
  1717. example: A%=SwapBytes%(&h1234) 'A% would be &h3412
  1718.  
  1719. FUNCTION: TestBit% (Number%, BitPosition%)
  1720. Returns -1 if the specified bit (BitPosition%=O to 15) of the 2-byte integer
  1721. Number% is ON (bit equal to 1) and returns O if the bit is OFF (bit equal to O)
  1722. example: A%=TestBit%(Temp%,12) 
  1723. 'A% would be -1 if bit 12 (binary value 4O96) of Temp% is a 1
  1724. 'A% would be  O if bit 12 (binary value 4O96) of Temp% is a O
  1725. 'note: Bit 15 is the most-significant-bit and Bit O is the least-significant-bit
  1726.  
  1727. FUNCTION: UnsComp% (Value1%,Value2%)
  1728. Performs an UNsigned comparison of the two 16-bit signed integer values.
  1729.  
  1730.               signed     unsigned     unsigned
  1731.               decimal     decimal    hexadecimal
  1732.              ────────    ────────    ───────────
  1733.  ┌──largest       -1  =    65535  =    &hFFFF 
  1734.  │     ∙      -32768  =    32768  =    &h8OOO
  1735.  │     ∙       32767  =    32767  =    &h7FFF
  1736.  └──smallest       O  =        O  =    &hOOOO
  1737.  
  1738. example: X% = UnsComp% (V1%,V2%)  'X% will be -1 if V1% < V2% ─┐
  1739.                                   'X% will be  O if V1% = V2%  ├─UNsigned
  1740.                                   'X% will be +1 if V1% > V2% ─┘ comparison
  1741.  
  1742. ┌─────────────────────────────────────────────────────────────────────────────┐
  1743. │         SCREEN (ANSI) FUNCTIONS                                             │
  1744. └─────────────────────────────────────────────────────────────────────────────┘
  1745. The following functions/subroutines operate on the current ANSI device, which
  1746. can be changed by the ANSIHandle subroutine.  The default ANSI device is
  1747. input=keyboard and output=screen, both of which are redirectable from the DOS 
  1748. command line. ex: CTTY COM1
  1749.                   PROGNAME
  1750.        --or-- ex: PROGNAME <COM1 >COM1
  1751.  
  1752. FUNCTION: ANSIBgColor%
  1753. Returns the last background color used in a call to the ANSIColor subroutine.
  1754. example: ANSIColor 3,4
  1755.          BG%=ANSIBgColor%  'BG% would be 4
  1756.  
  1757. SUBROUTINE: ANSICls
  1758. Clears the screen on the ANSI output device in the current colors.  The ANSI
  1759. cursor is also placed at the "home" position (upper-left corner of the screen
  1760. where row=1 and column=1).
  1761. example:  ANSICls
  1762.  --or--   Call ANSICls
  1763.  
  1764. SUBROUTINE: ANSIColor Foreground%, Background%
  1765. Changes the colors on the ANSI output device to the values specified.  Note
  1766. that this function automatically maps Quick-BASIC's colors into ANSI colors.
  1767. example: ANSIColor 31,1
  1768.         'sets ANSI colors to blinking-bright-white on blue background
  1769.  
  1770. SUBROUTINE: ANSIComInit ComPortNum%, BaudRate%, Parity%, WordSize%, StopBits%
  1771. Initializes the specified communications (serial) port for use with the other
  1772. ANSI commands.  Valid values are:
  1773.      ComPortNum% = 1 through 4 (for COM1 through COM4)
  1774.      BaudRate%   = 15O, 3OO, 6OO, 12OO, 24OO, 48OO, 96OO
  1775.      Parity%     = O(none)  1(odd)  2(even) 
  1776.      WordSize%   = 7 or 8 bits
  1777.      StopBits%   = 1 or 2
  1778. Note: If you are planning to use the other ANSI commands after initializing a
  1779.       com port, you must specify the ANSI handle as the negative equivalent of
  1780.       the com port number (using the ANSIHandle command).
  1781. example: ANSIComInit 2,96OO,O,8,1
  1782.         'init COM2 with 96OO baud, no parity, 8 bit data, 1 stop bit
  1783.          ANSIHandle -2
  1784.         'a negative handle number indicates a com port (in this case -2 = COM2)
  1785.  
  1786. FUNCTION: ANSIComStatus% (ComPortNum%)
  1787. Retrieves the status of the specified communications (serial) port.  Each bit of
  1788. the returned value has a particular meaning as shown below:
  1789.    Bit  Hex Value  Meaning
  1790.      O =  &hOOO1   CTS has changed
  1791.      1 =  &hOOO2   DSR has changed
  1792.      2 =  &hOOO4   Trailing Edge Ring Detector
  1793.      3 =  &hOOO8   Carrier Detect has changed
  1794.      4 =  &hOO1O   CTS (Clear To Send)
  1795.      5 =  &hOO2O   DSR (Data Set Ready)
  1796.      6 =  &hOO4O   Ring Indicator
  1797.      7 =  &hOO8O   Carrier Detect
  1798.      8 =  &hO1OO   Received Data is now ready to be retrieved from the UART
  1799.      9 =  &hO2OO   Overrun Error
  1800.     1O =  &hO4OO   Parity Error
  1801.     11 =  &hO8OO   Framing Error
  1802.     12 =  &h1OOO   Break Detect
  1803.     13 =  &h2OOO   Transmitter Holding Register is empty
  1804.     14 =  &h4OOO   Transmitter Shift Register is empty
  1805.     15 =  &h8OOO   Time Out (if this bit is 1, the other bits are unpredictable)
  1806. example: Stat% = ANSIComStatus% (3) 'get the status of COM3
  1807.          Ring% = (Stat% AND &hOO4O) 'is the COM3 modem phone line ringing ?
  1808.          If Ring% then Print "The phone is ringing !"
  1809.  
  1810. SUBROUTINE: ANSICsrRest 
  1811. Restores the cursor to the position last saved by the ANSICsrSave subroutine.
  1812. example: ANSICsrRest
  1813.  --or--  Call ANSICsrRest
  1814.  
  1815. SUBROUTINE: ANSICsrSave 
  1816. Saves the coordinates of the current cursor position so that it can be restored
  1817. by the ANSICsrRest subroutine.
  1818. example: ANSICsrSave
  1819.  --or--  Call ANSICsrSave
  1820.  
  1821. SUBROUTINE: ANSIDelLine 
  1822. Deletes the current line (using default ANSI colors) starting at the current
  1823. cursor position and ending at the rightmost column.
  1824. example: ANSIDelLine
  1825.  --or--  Call ANSIDelLine
  1826.  
  1827. SUBROUTINE: ANSIDown NumRows%
  1828. Moves the ANSI cursor down the specified number of rows.  If the cursor 
  1829. reaches the bottom line, no additional movement takes place.
  1830. example: ANSIDown 5 'moves the ANSI cursor down 5 rows
  1831.  
  1832. FUNCTION: ANSIFgColor%
  1833. Returns the last foreground color used in a call to the ANSIColor subroutine.
  1834. example: ANSIColor 3,4
  1835.          FG%=ANSIFgColor%  'FG% would be 3
  1836.  
  1837. SUBROUTINE: ANSIHandle Handle%
  1838. Specifies the DOS file handle for the default ANSI device.  The standard DOS
  1839. file handles are:
  1840.   O = STDIN   (keyboard)
  1841.   1 = STDOUT  (screen)
  1842.   2 = STDERR  (screen - used for error messages)
  1843.   3 = STDAUX  (COM1: serial port)
  1844.   4 = STDPRN  (LPT1: printer/parallel port)
  1845. If ANSIHandle is not called, the default is (input=keyboard, output=screen) 
  1846. which can be redirected from the DOS command line (e.g. TEMP <COM1 >COM1 ).
  1847. Note: This routine changes the value of the ANSI input handle AND the ANSI
  1848.       output handle.
  1849. Note: If the specified handle is negative (e.g. -1 to -4) then the ANSIKey% and
  1850.       ANSIPrt routines use the BIOS Int 14h com port functions to access
  1851.       COM1 (if -1) through COM4 (if -4).  In MOST (but not all) cases, the
  1852.       com port must be initialized using the ANSIComInit subroutine.
  1853. example: ANSIHandle 3   'set ANSI i/o to COM1: (use DOS)
  1854. example: ANSIHandle -2  'set ANSI i/o to COM2: (use BIOS)
  1855.  
  1856. SUBROUTINE: ANSIHandleIn Handle%
  1857. Changes the ANSI input handle only, which is used by the ANSIKey% function.
  1858. example: ANSIHandleIn 5 'set ANSI input handle to 5 (an open DOS file)
  1859.  
  1860. SUBROUTINE: ANSIHandleOut Handle%
  1861. Changes the ANSI output handle only, which is used by the ANSIPrt subroutine.
  1862. example: ANSIHandleOut 5 'set ANSI output handle to 5 (an open DOS file)
  1863.  
  1864. SUBROUTINE: ANSIHome 
  1865. Places the ANSI cursor at the "home" position (upper-left corner of the
  1866. screen where row=1 and column=1).
  1867. example: ANSIHome
  1868.  --or--  Call ANSIHome
  1869.  
  1870. FUNCTION: ANSIKey%
  1871. Reads and returns the ASCII value of the next keystroke from the ANSI input
  1872. device.  If no keystroke is pending, then the return value is -1.
  1873. This routine does not convert extended keycodes (as GetKey% and WaitKey% do), it
  1874. would simply return a null (zero) as the preamble code which would require your
  1875. program to retrieve the scan code as the next character.  Standard ANSI keycodes
  1876. (up,down,right,left) would return ESCape (as ASCII 27) followed by the
  1877. left-bracket "[" (as ASCII 91), followed by the ANSI-sequence-end-code.
  1878. ANSI arrow-key codes:  up=Esc[A   down=Esc[B   right=Esc[C   left=Esc[D
  1879. example: AKey%=ANSIKey% 'AKey% contains next character from ANSI input device
  1880. Note: On three-wire RS-232 systems (Tx,Rx,GND), connect DSR to DTR and 
  1881.       connect RTS to CTS.
  1882. >>>Please bear in mind that the ANSIKey% function is not buffered, and therefore
  1883. if it is used to read communications (serial) port data, it MUST be called
  1884. often enough to prevent incoming data from overwriting the previous UART
  1885. receive data.  This is referred to as "polling" the serial port.  Serious
  1886. communications software would require "interrupt-driven" routines for
  1887. serial port I/O (especially input). The GPS library does NOT provide that.<<<
  1888.  
  1889. SUBROUTINE: ANSILeft NumColumns%
  1890. Moves the ANSI cursor the specified number of columns to the left.  If the
  1891. cursor reaches the leftmost column, no additional movement takes place.
  1892. example: ANSILeft 15 'moves the ANSI cursor 15 columns to the left
  1893.  
  1894. SUBROUTINE: ANSILoc Row%, Column%
  1895. Places the ANSI cursor at the specified row and column.  The upper-left corner
  1896. of the screen would be specified by Row%=1 and Column%=1.  Note that some older
  1897. ANSI drivers do not allow the cursor to be placed on row 25.
  1898. example: ANSILoc 12,4O 'places the ANSI cursor at row=12 and column=4O
  1899.  
  1900. SUBROUTINE: ANSIPrt Text$
  1901. Prints the Text$ string to the ANSI output device.  Note: This function does NOT
  1902. print a return/line-feed after printing the string.  The ANSI cursor is left at
  1903. the position following the last character of Text$.
  1904. example: ANSIPrt "Now is the time for all good programmers to abandon C."
  1905.  
  1906. SUBROUTINE: ANSIPrtC Text$
  1907. This routine is identical to ANSIPrt, except that it DOES print a
  1908. return/line-feed after printing the string.
  1909. example:  ANSIPrtC "The quick" : ANSIPrtC "brown fox"
  1910.           This would cause printing to be done on two lines.
  1911.  
  1912. SUBROUTINE: ANSIPrtNum Number%
  1913. Prints the specified 2-byte integer Number% to the ANSI output device.
  1914. Note: This function does NOT add a leading space to positive numbers as BASIC
  1915. does.  The ANSI cursor is left at the position following the last digit of
  1916. Number%.
  1917. example: ANSIPrt "(" : ANSIPrtNum 12345% : ANSIPrt ")"   'prints (12345)
  1918.  
  1919. SUBROUTINE: ANSIRight NumColumns%
  1920. Moves the ANSI cursor the specified number of columns to the right.  If the
  1921. cursor reaches the rightmost column, no additional movement takes place.
  1922. example: ANSIRight 35 'moves the ANSI cursor 35 columns to the right
  1923.  
  1924. SUBROUTINE: ANSIUp NumRows%
  1925. Moves the ANSI cursor up the specified number of rows.  If the cursor 
  1926. reaches the top line, no additional movement takes place.
  1927. example: ANSIUp 4 'moves the ANSI cursor up 4 rows
  1928.  
  1929. ┌─────────────────────────────────────────────────────────────────────────────┐
  1930. │         SCREEN FUNCTIONS                                                    │
  1931. └─────────────────────────────────────────────────────────────────────────────┘
  1932. NOTE: ALL of the GPS library screen functions have been designed to work in
  1933.       TEXT MODE ONLY !!! Be sure that you supply each screen function/subroutine
  1934.       with row values between 1 and 25 and column values between 1 and 8O,
  1935.       otherwise most will return without performing the specified function.
  1936.  
  1937. SUBROUTINE: AttrColor Attr%, Foreground%, Background%
  1938. Splits a color-attribute-byte value (Attr%) into separate variables (Foreground%
  1939. and Background%).
  1940. example: AttrColor 159,Fore%,Back% 'sets Fore%=31 (blinking bright white) and
  1941.                                    'sets Back%=1  (blue background)
  1942.  
  1943. SUBROUTINE: Clrs Attr%
  1944. Clears the screen using the colors specified by the color-attribute-byte
  1945. (Attr%).  See the beginning of this documentation for an explanation of this
  1946. byte.  Note: Using the Clrs subroutine does NOT alter the default colors.
  1947. example: Clrs 7 'will clear the screen using foreground=7 background=O
  1948.  
  1949. FUNCTION: ColorAttr%(Foreground%, Background%)
  1950. Returns a color-attribute-byte value from the specified Foreground% and
  1951. Background% color values.  This returned value can be used in several of the
  1952. GPS library screen functions.
  1953. example: FColor%=31 'blinking bright white foreground
  1954.          BColor%=1  'blue background
  1955.          A%=ColorAttr%(FColor%,BColor%) '(color-attribute-byte) A% would be 159
  1956.  
  1957. FUNCTION: ColorPDQ%
  1958. Returns the current color-attribute-byte value for a program LINKed with the PDQ
  1959. libraries from Crescent Software.  There is a description of this byte at the
  1960. beginning of this documentation.
  1961. example: A%=ColorPDQ%
  1962. ** Use only if LINKed with PDQ libraries
  1963. ** Will not work inside QB editor/environment or with Quick-BASIC libraries
  1964.  
  1965. FUNCTION: ColorQB%
  1966. Returns the current color-attribute-byte value for a program LINKed with the
  1967. standard Quick-BASIC libraries (BCOM45.LIB and QB.LIB).
  1968. example: A%=ColorQB%
  1969. ** Use only if LINKed with Quick-BASIC libraries
  1970. ** Will not work inside QB editor/environment or with PDQ libraries
  1971.  
  1972. FUNCTION: MemToScreen% (see ScreenToMem% function)
  1973.  
  1974. SUBROUTINE: Prnt Text$, Row%, Column%, Attr%
  1975. Prints the Text$ on the screen at (Row%,Column%) using the colors specified by
  1976. the color-attribute-byte (Attr%).  There is a description of this byte at the
  1977. beginning of this documentation.  Note: the default colors are NOT altered.
  1978. example: Prnt "This is a test",12,35,31
  1979.         'prints the text on (row=12,column=35) using white/blue colors
  1980.  
  1981. SUBROUTINE: PrntOver Text$, Row%, Column%
  1982. Prints the Text$ on the screen at (Row%,Column%) using the colors already on
  1983. the screen at the position where each character is to be printed.
  1984. example: COLOR 14,1  'sets color to yellow/blue
  1985.          CLS         'clears the screen with yellow/blue
  1986.          COLOR 12,3  'sets color to red/cyan (screen is still yellow/blue)
  1987.          PrntOver "This is a test",12,35
  1988.         'prints the text on (row=12,column=35) in yellow/blue
  1989.  
  1990. SUBROUTINE: ScreenAOX Row1%,Column1%,Row2%,Column2%,ANDmask%,ORmask%,XORmask%
  1991. Changes the ASCII-character and color-attribute within the screen "box"
  1992. (upper-left=Row1%,Column1%  lower-right=Row2%,Column2%) with the 2-byte mask
  1993. values.  The low-byte of each mask operates on the ASCII character while the
  1994. high-byte of each mask operates on the color-attribute-byte.  The order of
  1995. operation is AND-OR-XOR.  For example:
  1996. ScreenAOX 1,1,25,8O,&hFFFF,&h8OOO,      O  'set blink bit ON
  1997. ScreenAOX 1,1,25,8O,&h7FFF,     O,      O  'set blink bit OFF
  1998. ScreenAOX 1,1,25,8O,&hFFFF,&hO8OO,      O  'set bold bit ON
  1999. ScreenAOX 1,1,25,8O,&hF7FF,     O,      O  'set bold bit OFF
  2000.  
  2001. SUBROUTINE: ScreenBlink Row1%,Column1%,Row2%,Column2%,BlinkState%
  2002. Changes the blink bit for each character within the screen "box"
  2003. (upper-left=Row1%,Column1%  lower-right=Row2%,Column2%) according to the
  2004. BlinkState%.  If BlinkState% is zero then blink is turned OFF, otherwise
  2005. blink is turned ON.  For example:
  2006. ScreenBlink 1,1,25,8O,1 'turn blink ON  for entire screen
  2007. ScreenBlink 1,1,25,8O,O 'turn blink OFF for entire screen
  2008.  
  2009. SUBROUTINE: ScreenBold Row1%,Column1%,Row2%,Column2%,BoldState%
  2010. Changes the bold bit for each character within the screen "box"
  2011. (upper-left=Row1%,Column1%  lower-right=Row2%,Column2%) according to the
  2012. BoldState%.  If BoldState% is zero then bold is turned OFF, otherwise
  2013. bold is turned ON.  For example:
  2014. ScreenBold 1,1,25,8O,1 'turn bold ON  for entire screen
  2015. ScreenBold 1,1,25,8O,O 'turn bold OFF for entire screen
  2016.  
  2017. SUBROUTINE: ScreenBox Row1%,Column1%,Row2%,Column2%,BoxType%,ColorAttrib%
  2018. Draws a 'box' on a text-mode screen using the specified ColorAttrib%
  2019. (color-attribute-byte) value.  The upper-left corner of the box is specified
  2020. by Row1%, Column1% and the lower-right corner is specified by Row2%, Column2%.
  2021. The BoxType% value specifies the type of box to draw (1OO to 1O4).  Note that
  2022. the inside of the box is filled with spaces in the specified color.
  2023. ┌───┐  ╒═══╕  ╓───╖  ╔═══╗  █▀▀▀█    Numbers outside the range of 1OO to 1O4
  2024. │1OO│  │1O1│  ║1O2║  ║1O3║  ▌1O4▐    will cause the ASCII character to be used
  2025. └───┘  ╘═══╛  ╙───╜  ╚═══╝  █▄▄▄█    as the border of the box. (e.g. 32=space)
  2026. example: ScreenBox 1,1,25,8O,1OO,3O
  2027. 'draw a single-line box covering the entire screen
  2028. '(upper-left row,col=1,1 to lower-right row,col=25,8O)     ┌──yellow    ┌──blue
  2029. 'using yellow foreground on blue background        3O = ( 14 + ( 16 * ( 1 ) )
  2030.  
  2031. SUBROUTINE: ScreenFade Fade%,MemSeg%
  2032. Transfers the 4OOO-byte text screen image stored at memory location MemSeg%:OOOO
  2033. to the screen using the specified Fade%. (see the Fade Table in the Appendix).
  2034. Note that the screen image must be stored at offset OOOO within the given 
  2035. segment (MemSeg%).  This can be done by using the MemCopy command and others.
  2036. example: ScreenFade 255,&h1234
  2037. 'copy 4OOO-byte image at 1234:OOOO to the screen using random Fade%=255
  2038. 'Note: The current version of this routine passes parameters by value (BYVAL).
  2039.  
  2040. SUBROUTINE: ScreenFill Row1%,Column1%,Row2%,Column2%,ASCIIChar%,ColorAttr%
  2041. Fills the screen "box" (upper-left=Row1%,Column1%  lower-right=Row2%,Column2%)
  2042. with the specified ASCIIChar% and ColorAttr%.  If ASCIIChar% is -1 then
  2043. characters remain unaltered.  If ColorAttr% is -1 then color attributes remain
  2044. unaltered.  For example: (ASCII 32=space  ATTR 3O is yellow/blue)
  2045. ScreenFill 1,1,25,8O,32,3O 'fill screen with spaces in yellow/blue colors
  2046. ScreenFill 1,1,25,8O,32,-1 'fill screen with spaces (colors unchanged)
  2047. ScreenFill 1,1,25,8O,-1,3O 'fill screen in yellow/blue colors (ASCII unchanged)
  2048.  
  2049. FUNCTION: ScreenLoad% (FileName$)
  2050. Loads the 4OOO-byte text screen image file from the specified FileName$ to
  2051. the screen. The function returns -1 if any file errors occur, otherwise it
  2052. returns O.  Note that this function can also load 4OO7-byte BSAVE files.
  2053. example: ErrCode% = ScreenLoad%("TEST.SCN") 'load file to screen
  2054.  
  2055. SUBROUTINE: ScreenMarquee Row1%,Column1%,Row2%,Column2%,Attr%
  2056. Places a "marquee" (i.e. flashing box) around the specified screen coordinates.
  2057. The upper-left corner is defined by (Row1%,Column1%) and the lower-right corner
  2058. is defined by (Row2%,Column2%).  The marquee colors are specified by the Attr%
  2059. color-attribute-byte operand.  Note that only low-intensity foreground and
  2060. background colors are used.  The area, inside the box, is not altered.
  2061. example: ScreenMarquee 1,1,25,8O,83
  2062. 'draw a marquee around the entire screen
  2063. '(upper-left row,col=1,1 to lower-right row,col=25,8O)    ┌─cyan       ┌─magenta
  2064. 'using cyan and magenta                            83 = ( 3 + ( 16 * ( 5 ) )
  2065.  
  2066. SUBROUTINE: ScreenPrint
  2067. Prints the current screen (same as pressing the Shift+Print-Screen key).
  2068. example: ScreenPrint
  2069.          ---or---
  2070.          Call ScreenPrint
  2071.  
  2072. FUNCTION: ScreenSave% (FileName$)
  2073. Saves the current text mode screen to the specified FileName$.  The file size
  2074. is always 4OOO bytes.  The function returns -1 if any file errors occur,
  2075. otherwise it returns O.
  2076. example: ErrCode% = ScreenSave%("TEST.SCN") 'save screen to file
  2077.  
  2078. SUBROUTINE: ScreenScroll Numlines%,Row1%,Column1%,Row2%,Column2%,Attribute%
  2079. Causes the screen to scroll (up if NumLines% is positive, down if NumLines% is
  2080. negative) by the specified number of lines (NumLines%).  The portion of the
  2081. screen to be scrolled is determined by the upper-left corner (Row1%,Column1%)
  2082. and the lower-right corner (Row2%,column2%).  The lines which are left vacant
  2083. by the scrolling process are filled in with spaces in the color specified by
  2084. Attribute% (color-attribute-byte format).
  2085. example: ScreenScroll (-5,1,1,25,8O,3O)
  2086. 'scroll-down entire screen by 5 lines - fill in with spaces (yellow on blue)
  2087.  
  2088. SUBROUTINE: ScreenString Text$,Row%,Column%,NumBytes%
  2089. Copies the specified number of bytes (NumBytes%) of text from the screen
  2090. (at Row%,Column%) to a variable-length string variable (e.g. Text$).  Note that
  2091. only text is copied.  The color attributes are ignored.
  2092. example:  Locate 12,4O : Print "The quick brown fox jumps over the lazy dog"
  2093.           ScreenString Text$,12,5O,9  'means Text$ will contain "brown fox"
  2094.  
  2095. FUNCTION: ScreenTicker%(Message$,Row%,StartColumn%,EndColumn%,ColorAttrib%,_
  2096.                         ExitKey%,Speed%)
  2097. Places a 'ticker-tape' message on the screen on Row% between StartColumn% and
  2098. EndColumn% (inclusive).  Message$ contains the text to be displayed and can be
  2099. longer than the message box area on the screen.  The ColorAttrib% operand
  2100. (in color-attribute-byte format) specifies the screen colors to be used for 
  2101. the message box.  The Speed% operand specifies the time delay between character
  2102. movement and should be between (1=fast and 1O=slow).  The ExitKey% operand
  2103. specifies what key will cause the 'ticker-tape' message to terminate (O=any 
  2104. key).  The key-code values are listed in the appendix.  The message-box-area
  2105. of the screen is restored to its previous state when the function ends.  The
  2106. return value of this function (ScreenTicker%) is the key-code of the key used
  2107. to terminate this function (same as ExitKey% except when ExitKey%=O (any key)
  2108. is used).
  2109.  
  2110. FUNCTION: ScreenToMem% (MemSeg%,MemPtr%,Row1%,Column1%,Row2%,Column2%)
  2111. FUNCTION: MemToScreen% (MemSeg%,MemPtr%,Row%,Column%)
  2112. These two functions allow a "box" of ASCII color text on the screen to be 
  2113. stored-to/restored-from memory.
  2114. To store a block of text:
  2115.    A%=ScreenToMem%(MemSeg%,MemPtr%,Row1%,Column1%,Row2%,Column2%)
  2116.    This command will store the block of text (upper-left corner=Row1%,Column1%
  2117.    and lower-right corner=Row2%,Column2%) to memory starting at MemSeg%:MemPtr%.
  2118.    The return value ScreenToMem% contains the number of bytes needed to store
  2119.    that block.  The "box" is stored as follows: a 2-byte video offset, then 
  2120.    1-byte for number of rows, then 1-byte for number of columns, then 2 bytes
  2121.    for each character inside the "box".  
  2122. To restore a block of text:
  2123.    A%=MemToScreen%(MemSeg%,MemPtr%,Row%,Column%)
  2124.    This command will restore the block "box" (previously stored at 
  2125.    MemSeg%:MemPtr%) to the screen coordinates Row%,Column%.  If Row% is 
  2126.    specified as zero, then the "box" is placed at the same position on the
  2127.    screen where it came from.  Make sure the "box" will fit on the screen where
  2128.    you place it.  The return value is the number of bytes used to restore it.
  2129. Note: rows=1 to 25 and columns=1 to 8O.
  2130.  
  2131. SUBROUTINE: SetColorPDQ Attribute%
  2132. Sets the color-attribute-byte to the specified Attribute% for a program LINKed
  2133. with the PDQ libraries from Crescent Software. (see also ColorPDQ% function)
  2134. example: SetColorPDQ 3O  'sets color yellow on blue
  2135. ** Use only if LINKed with PDQ libraries
  2136. ** Will not work inside QB editor/environment or with Quick-BASIC libraries
  2137.  
  2138. SUBROUTINE: SetColorQB Attribute%
  2139. Sets the color-attribute-byte to the specified Attribute% for a program LINKed
  2140. with the standard Quick-BASIC libraries (BCOM45.LIB and QB.LIB).
  2141. example: SetColorQB 3O 'sets color yellow on blue (see also ColorQB% function)
  2142. ** Use only if LINKed with Quick-BASIC libraries
  2143. ** Will not work inside QB editor/environment or with PDQ libraries
  2144.  
  2145. SUBROUTINE: SetTextMode
  2146. Changes the screen mode to 8Ox25 text mode. (BIOS mode: 3=color  7=mono)
  2147. example: Call SetTextMode
  2148.  
  2149. SUBROUTINE: SetVideoSeg NewVideoSeg%
  2150. The SetVideoSeg subroutine sets the video segment for using virtual screens
  2151. with all of the GPS library screen functions.  This routine sets the value
  2152. that is to be returned by the VideoSeg% function.
  2153. example: SetVideoSeg O  'resets the video segment to the REAL video segment
  2154.          'MONO systems=&hBOOO (or -2O48O)    COLOR systems=&hB8OO (or -18432)
  2155.          SetVideoSeg &h7OOO 'sets video segment for virtual screens to &h7OOO
  2156.  
  2157. SUBROUTINE: SetVideoSegPDQ NewVideoSeg%
  2158. same as SetVideoSeg except that it sets the virtual video segment for programs
  2159. linked with PDQ.  This routine sets the value that is returned by VideoSegPDQ%.
  2160. Note: This routine also updates the GPS library function VideoSeg%.
  2161. example: SetVideoSegPDQ O  'resets the video segment to the REAL video segment
  2162.          'MONO systems=&hBOOO (or -2O48O)    COLOR systems=&hB8OO (or -18432)
  2163.          SetVideoSegPDQ &h7OOO 'sets video segment for virtual screens to &h7OOO
  2164. ** Use only if LINKed with PDQ libraries
  2165. ** Will not work inside QB editor/environment or with Quick-BASIC libraries
  2166.  
  2167. SUBROUTINE: SetVideoSegQB NewVideoSeg%
  2168. same as SetVideoSeg except that it sets the virtual video segment for programs
  2169. linked with QB.  It affects only LOCATE and PRINT (CLS uses a BIOS call).  This
  2170. routine sets the value that is returned by VideoSegQB%.
  2171. Note: This routine also updates the GPS library function VideoSeg%.
  2172. example: SetVideoSegQB O  'resets the video segment to the REAL video segment
  2173.          'MONO systems=&hBOOO (or -2O48O)    COLOR systems=&hB8OO (or -18432)
  2174.          SetVideoSegQB &h7OOO 'sets video segment for virtual screens to &h7OOO
  2175. ** Use only if LINKed with Quick-BASIC libraries
  2176. ** Will not work inside QB editor/environment or with PDQ libraries
  2177.  
  2178. FUNCTION: VideoPtr% (Row%, Column%)
  2179. Returns the pointer (offset) in video memory where Row%,Column% is located.
  2180. It is useful whenever you wish to work directly with text-mode video memory.
  2181. example: A% = VideoPtr%(12,4O)  'A% would be 1838
  2182.          'same as A% = ( ( Row% - 1 ) * 16O ) + ( ( Column% - 1 ) * 2 )
  2183.  
  2184. FUNCTION: VideoSeg%
  2185. The VideoSeg% function returns the current video memory segment for use with
  2186. GPS library screen functions.
  2187. example: VSeg% = VideoSeg% : DEF SEG=VSeg% : X% = PEEK(&hO5OO)
  2188.          'see the SetVideoSeg subroutine
  2189.  
  2190. FUNCTION: VideoSegPDQ%
  2191. The VideoSeg% function returns the current video memory segment for use with
  2192. PDQ library screen functions.
  2193. example: VSegPDQ% = VideoSegPDQ% : DEF SEG=VSegPDQ% : X% = PEEK(&hO5OO)
  2194.          'see the SetVideoSegPDQ subroutine
  2195. ** Use only if LINKed with PDQ libraries
  2196. ** Will not work inside QB editor/environment or with Quick-BASIC libraries
  2197.  
  2198. FUNCTION: VideoSegQB%
  2199. The VideoSeg% function returns the current video memory segment for use with
  2200. Quick-BASIC's screen functions (LOCATE and PRINT).
  2201. example: VSegQB% = VideoSegQB% : DEF SEG=VSegQB% : X% = PEEK(&hO5OO)
  2202.          'see the SetVideoSegQB subroutine
  2203. ** Use only if LINKed with Quick-BASIC libraries
  2204. ** Will not work inside QB editor/environment or with PDQ libraries
  2205.  
  2206. ┌─────────────────────────────────────────────────────────────────────────────┐
  2207. │         STRING FUNCTIONS                                                    │
  2208. └─────────────────────────────────────────────────────────────────────────────┘
  2209. Note: Do NOT use fixed-length strings with these functions !!!
  2210.  
  2211. FUNCTION: AddCRLF$ (Text$)
  2212. Returns the specified string with a <carriage-return><line-feed> combination
  2213. appended to the end of it.
  2214. example: X$=AddCRLF$(Y$) 'would be the same as X$=Y$+CHR$(13)+CHR$(1O)
  2215.  
  2216. FUNCTION: AppLink$
  2217. Returns a 16-byte string containing the contents of the intra-application area
  2218. which is located at OOOO:O4FO in the BIOS data area of low memory.  This area
  2219. can be used to hold data between CHAINed programs etc.  (see SetAppLink)
  2220. example: SetApplink "This is a test"
  2221.          A$=AppLink$ 'this would retrieve the string "This is a test  "
  2222.  
  2223. FUNCTION: AscMid% (Text$, Position%)
  2224. Returns the ASCII value of the character located at Position% in the string
  2225. Text$.  This function performs the same task as ASC(MID$(Text$,Position%)) but
  2226. it is faster.
  2227. example: A% = AscMid%("ABCDEFGH",4) 'A% would be equal to 68 (ASCII value of D)
  2228.  
  2229. FUNCTION: Bin$ (IntVal%)
  2230. Returns a 16-byte string representing the unsigned binary value of IntVal%.
  2231. example: A$=Bin$(&h1234)
  2232.         'A$ would be "OOO1OO1OOO11O1OO"  actual zeros are used (not letter O)
  2233.         '             └──┤└──┤└──┤└──┤
  2234.         '                1   2   3   4 hexadecimal
  2235.         'The Replace subroutine could now be used to convert all zeros in A$ to
  2236.         'the letter O in order to enhance readability.
  2237.          Replace A$,48,79 'replace all zeros (ASCII=48) with letter O (ASCII=79)
  2238.  
  2239. FUNCTION: Center$ (Text$, LineWidth%)
  2240. This function returns a string that is (LineWidth%) characters in length with
  2241. Text$ centered inside it.  Leading and/or trailing spaces are used to pad the
  2242. string to the appropriate length.  If Text$ is longer than LineWidth%, it is
  2243. truncated to fit.
  2244. example: A$=Center$("ABCD",7)     'A$ would be " ABCD  "
  2245.          A$=Center$("ABCDE",7)    'A$ would be " ABCDE "
  2246.          A$=Center$("ABCDEF",7)   'A$ would be "ABCDEF "
  2247.          A$=Center$("ABCDEFG",7)  'A$ would be "ABCDEFG"
  2248.  
  2249. FUNCTION: ChainLink$
  2250. Returns a 96-byte string containing the contents of the unused 96-byte area
  2251. at the end of text-mode video memory which is located at VideoSeg%:OFAO.
  2252. This area can be used to hold data between CHAINed programs etc.  Note that
  2253. this function must not be used in text modes utilizing more than 8O columns
  2254. and 25 lines (such as 132 column modes or 43/5O/66 line modes).
  2255. (see SetChainLink)
  2256. example: SetChainlink "This is a test"
  2257.          A$=ChainLink$ 'this would retrieve a 96-byte string 
  2258.  
  2259. SUBROUTINE: ChgCase Text$
  2260. Changes the case of every alphabetic character in the Text$ string (i.e.
  2261. lower-case becomes upper-case and upper-case becomes lower-case).
  2262. example: Temp$="A-b-C-d-E-f"
  2263.          ChgCase Temp$  'Temp$ would be changed to "a-B-c-D-e-F"
  2264. NOTE: The string Text$ is changed (in place) and therefore MUST be a string
  2265.       variable !!!  It can NOT be a literal string ("x") or a string function
  2266.       resultant (such as X$+Y$) !!!
  2267.  
  2268. SUBROUTINE: ChgMid Text$, Position%, NewValue%
  2269. Changes the ASCII value of the character at Position% in the string Text$ to
  2270. the ASCII value specified by NewValue%.
  2271. example: Text$="ABCDEFG"
  2272.          ChgMid Text$,3,32 'Text$ would be changed to "AB DEFG"
  2273. NOTE: The string Text$ is changed (in place) and therefore MUST be a string
  2274.       variable !!!  It can NOT be a literal string ("x") or a string function
  2275.       resultant (such as X$+Y$) !!!
  2276.  
  2277. FUNCTION: InstrFwd% (StartAt%, SearchIn$, LookFor$)
  2278. Returns the position of the first occurrence of LookFor$ in SearchIn$.  The
  2279. forward order search begins at position StartAt%.  This function is identical
  2280. to INSTR(StartAt%,SearchIn$,LookFor$) except that it returns zero if the
  2281. LookFor$ string is null. (BASIC's INSTR function returns 1 - Why ?  Who Knows ?)
  2282. example: A%=INSTR    (1,"ABC","")   'A%=1
  2283.          A%=InstrFwd%(1,"ABC","")   'A%=O different from BASIC's INSTR
  2284.          A%=InstrFwd%(1,"ABC","B")  'A%=2 same as BASIC's INSTR
  2285.  
  2286. FUNCTION: InstrRev% (StartAt%, SearchIn$, LookFor$)
  2287. Returns the position of the LAST occurrence of LookFor$ in SearchIn$.
  2288. The REVERSE-ORDER search begins at position StartAt%.  If LookFor$ is null or
  2289. if StartAt% is zero, the function returns zero.  If StartAt% is negative or if
  2290. StartAt% is greater than the length of SearchIn$, then StartAt% is set to the
  2291. length of SearchIn$.
  2292. example: 'separate the path from the filename
  2293.          PF$="C:\TEMP\MISC\ABC.DAT"  'path+file (assume we don't know form yet)
  2294.          X%=Larger%(InstrRev%(-1,PF$,"\"),InstrRev%(-1,PF$,":"))
  2295.          P$=LEFT$(PF$,X%)  'Here's the path
  2296.          F$=MID$(PF$,X%+1) 'and here's the filename
  2297.  
  2298. FUNCTION: IntStr$  (IntVal%)
  2299. Returns a forward-order 2-byte string from the 2-byte integer value IntVal%.
  2300. This string can then be used in a FIELD or PUT statement etc.  The
  2301. forward-order means that the string can be sorted (unlike Quick-BASIC's
  2302. MKI$ function).
  2303. example: A$=IntStr$(&h1234)
  2304.  
  2305. FUNCTION: IStr$ (IntVal%)
  2306. Returns a string representation of the integer value (IntVal%) except that
  2307. there is no leading space.  It is exactly the same as LTRIM$(STR$(IntVal%)).
  2308.  
  2309. FUNCTION: LJustify$ (Text$, LineWidth%)
  2310. This function returns a string that is (LineWidth%) characters in length with
  2311. Text$ left-justified inside it.  Trailing spaces are used to pad the string to
  2312. the appropriate length.  If Text$ is longer than LineWidth%, it is truncated.
  2313. example: A$=LJustify$("ABCD",5)    'A$ would be "ABCD "
  2314.          A$=LJustify$("ABCDEFG",5) 'A$ would be "ABCDE"
  2315.  
  2316. FUNCTION: LongStr$ (LongVal&)
  2317. Returns a forward-order 4-byte string from the 4-byte (long) integer value
  2318. LongVal&.  This string can then be used in a FIELD or PUT statement etc.  The
  2319. forward-order means that the string can be sorted (unlike Quick-BASIC's
  2320. MKL$ function).
  2321. example: A$=LongStr$(&h12345678)
  2322.  
  2323. SUBROUTINE: LowerCase Text$
  2324. Changes any upper-case characters in Text$ to their lower-case equivalents.
  2325. example: Text$="AbCdEf"
  2326.          LowerCase Text$ 'Text$ would be "abcdef"
  2327. NOTE: The string Text$ is changed (in place) and therefore MUST be a string
  2328.       variable !!!  It can NOT be a literal string ("x") or a string function
  2329.       resultant (such as X$+Y$) !!!
  2330.  
  2331. FUNCTION: LStr$ (LongVal&)
  2332. Returns a string representation of the long integer value (LongVal&) except that
  2333. there is no leading space.  It is exactly the same as LTRIM$(STR$(LongVal&)).
  2334.  
  2335. SUBROUTINE: MemToString Text$,MemSeg%,MemPtr%,NumBytes%
  2336. Copies a block of memory starting at MemSeg%:MemPtr% and having a length (in
  2337. bytes) of NumBytes% into a variable-length string variable (e.g. Text$).
  2338. example: MemToString Text$,&hB8OO,O,4OOO 'copy color screen to Text$
  2339.                                          'note: DGROUP string area is small so
  2340.                                          '      you should use sparingly.
  2341.                                          'see also: StringToMem subroutine
  2342.  
  2343. FUNCTION: NoMid$ (Text$, StartPos%, NumChars%)
  2344. Returns the Text$ string with a section removed from it.  The section that is
  2345. removed begins at StartPos% and is NumChars% characters long.  Essentially
  2346. this function discards what BASIC's MID$ function keeps and vice versa.
  2347. example:  A$=  MID$("ABCDEFGHIJK",4,3) 'A$ would be "DEF"
  2348.           A$=NoMid$("ABCDEFGHIJK",4,3) 'A$ would be "ABCGHIJK"
  2349.  
  2350. FUNCTION: NoSegm$ (Text$, StartPos%, EndPos%)
  2351. Returns the Text$ string with a section removed from it.  The section that is
  2352. removed begins at StartPos% and continues to EndPos%.
  2353. example:  A$=NoSegm$("ABCDEFGHIJK",3,7) 'A$ would be "ABHIJK"
  2354.  
  2355. FUNCTION: NoSpace$ (Text$)
  2356. Returns a string (from Text$) containing no imbedded spaces or nulls.
  2357. example:  A$=NoSpace$("  Testing  1 2 3  ")   'A$ would be "Testing123"
  2358.  
  2359. FUNCTION: Repeat$ (Text$, NumTimes%)
  2360. Returns a string containing Text$ repeated (NumTimes%) number of times.
  2361. example:  A$=Repeat$("Testing",3)  'A$ would be "TestingTestingTesting"
  2362.  
  2363. SUBROUTINE: Replace Text$, OldChar%, NewChar%
  2364. Converts all characters, having an ASCII value of OldChar%, in Text$ to the
  2365. new ASCII value of NewChar%.
  2366. example: Text$="This is a test"
  2367.          Replace Text$,32,45 'Text$ would be "This-is-a-test"
  2368.                   space─┘  └─dash
  2369. NOTE: The string Text$ is changed (in place) and therefore MUST be a string
  2370.       variable !!!  It can NOT be a literal string ("x") or a string function
  2371.       resultant (such as X$+Y$) !!!
  2372.  
  2373. FUNCTION: Reverse$ (Text$)
  2374. Returns a string containing Text$ in reverse order.
  2375. example:  A$=Reverse$("ABCD")  'A$ would be "DCBA"
  2376.  
  2377. FUNCTION: RJustify$ (Text$, LineWidth%)
  2378. This function returns a string that is (LineWidth%) characters in length with
  2379. Text$ right-justified inside it.  Leading spaces are used to pad the string to
  2380. the appropriate length.  If Text$ is longer than LineWidth%, it is truncated.
  2381. Note: If truncation is necessary, the RIGHT-most characters are preserved.
  2382. example: A$=RJustify$("ABCD",5)    'A$ would be " ABCD"
  2383.          A$=RJustify$("ABCDEFG",5) 'A$ would be "CDEFG"
  2384.  
  2385. FUNCTION: Segm$ (Text$, StartPos%, EndPos%)
  2386. Returns the portion of Text$ which starts at StartPos% and ends at EndPos%.
  2387. example: A$=Segm$("ABCDEFGHIJK",5,7)  'A$ would be "EFG"
  2388.  
  2389. SUBROUTINE: SetChainLink Link$
  2390. Sets the contents of the unused 96-byte area at the end of text-mode video
  2391. memory equal to the string value Link$.  This area can be used to hold data
  2392. between CHAINed programs etc.  Note that this function must not be used in
  2393. text modes utilizing more than 8O columns and 25 lines (such as 132 column modes
  2394. or 43/5O/66 line modes).  The area is padded with spaces to the right if Link$
  2395. is less than 96 bytes in length. (see ChainLink$)
  2396. example: SetChainlink "This is a test"
  2397.          A$=ChainLink$ 'this would retrieve a 96-byte string 
  2398.  
  2399. SUBROUTINE: SetAppLink App$
  2400. Sets the contents of the 16-byte intra-application area equal to the specified
  2401. string value App$.  This area can hold data between CHAINed programs.  Note
  2402. that the area is padded with spaces to the right if App$ is less than 16 bytes
  2403. in length.  (see AppLink$)
  2404. example: SetApplink "This is a test"
  2405.          A$=AppLink$ 'this would retrieve the string "This is a test  "
  2406.  
  2407. FUNCTION: StrChkSum& (Text$)
  2408. Returns a long integer value representing the sum of all the bytes (ASCII 
  2409. values) in the Text$ string.
  2410. example:  A&=StrChkSum&("ABC") 'A& would be 198=65+66+67
  2411.  
  2412. SUBROUTINE: StringToMem Text$,MemSeg%,MemPtr%,NumBytes%
  2413. Copies a variable-length string (e.g. Text$) into a block of memory starting at
  2414. MemSeg%:MemPtr% and having a length (in bytes) of NumBytes%.
  2415. example: StringToMem Text$,&hB8OO,O,4OOO 
  2416.          'copy Text$ to color screen
  2417.          'note: DGROUP string area is small so you should use sparingly.
  2418.          '      If length of Text$ is larger than NumBytes%, then copying
  2419.          '      is stopped at count=NumBytes%.  If length of Text$ is
  2420.          '      smaller than NumBytes%, spaces are used to pad additional memory
  2421.          'see also: MemToString subroutine
  2422.  
  2423. FUNCTION: StrInt%  ( IntVal$ )
  2424. Returns a 2-byte integer value from the 2-byte string value IntVal$.  Note
  2425. that IntVal$ must have been made by the IntStr$ function because the StrInt%
  2426. function requires a forward-order string operand.  (see IntStr$)
  2427. example: A$=IntStr$(1234%)
  2428.          A%=StrInt%(A$) 'A% would be 1234
  2429.  
  2430. FUNCTION: StrLong& ( IntVal$ )
  2431. Returns a 4-byte (long) integer value from the 4-byte string value IntVal$.
  2432. Note that IntVal$ must have been made by the LongStr$ function because the
  2433. StrLong& function requires a forward-order string operand.  (see LongStr$)
  2434. example: A$=LongStr$(123456789&)
  2435.          A&=StrLong(A$) 'A& would be 123456789
  2436.  
  2437. FUNCTION: Trim$ (Text$)
  2438. Trims spaces from the left and right ends of Text$.  It is the same as using
  2439. RTRIM$(LTRIM$(Text$)).
  2440.  
  2441. FUNCTION: TrimLCase$ (Text$)
  2442. Trims spaces from the left and right ends of Text$ and also converts all
  2443. alphabetic characters to lower case.  It is the same as using
  2444. LCASE$(RTRIM$(LTRIM$(Text$))).
  2445.  
  2446. FUNCTION: TrimUCase$ (Text$)
  2447. Trims spaces from the left and right ends of Text$ and also converts all
  2448. alphabetic characters to upper case.  It is the same as using
  2449. UCASE$(RTRIM$(LTRIM$(Text$))).
  2450.  
  2451. SUBROUTINE: UpperCase Text$
  2452. Changes any lower-case characters in Text$ to their upper-case equivalents.
  2453. example: Text$="AbCdEf"
  2454.          UpperCase Text$ 'Text$ would be "ABCDEF"
  2455. NOTE: The string Text$ is changed (in place) and therefore MUST be a string
  2456.       variable !!!  It can NOT be a literal string ("x") or a string function
  2457.       resultant (such as X$+Y$) !!!
  2458.  
  2459. SUBROUTINE: XORString Text$, XORValue%
  2460. Performs the eXclusive-OR function (using XORValue%) on each character in the
  2461. string value Text$.  This makes it possible to implement a very simple 
  2462. encryption system.
  2463. example: Text$="@@@" : XORString Text$,1  'Text$ would be changed to "AAA"
  2464.                        XORString Text$,1  'Text$ would be changed back to "@@@"
  2465. NOTE: The string Text$ is changed (in place) and therefore MUST be a string
  2466.       variable !!!  It can NOT be a literal string ("x") or a string function
  2467.       resultant (such as X$+Y$) !!!
  2468.  
  2469. ┌─────────────────────────────────────────────────────────────────────────────┐
  2470. │           SYSTEM / MISCELLANEOUS FUNCTIONS                                  │
  2471. └─────────────────────────────────────────────────────────────────────────────┘
  2472. SUBROUTINE: ColdBoot
  2473. Performs a COLD boot on the PC like pressing the Reset button. (checks memory)
  2474. example: ColdBoot
  2475.          --or--
  2476.          Call ColdBoot
  2477.  
  2478. FUNCTION:   DOSVersion%
  2479. Returns the version of DOS currently in use on the PC (multiplied by 1OO).
  2480. example: DV%=DOSVersion%
  2481.          'if DOS version is 3.31 then DV%=331
  2482.          'if DOS version is 5.OO then DV%=5OO
  2483.  
  2484. SUBROUTINE: FormFeed
  2485. Sends a form-feed (ascii 12) to the printer (PRN device usually LPT1:).
  2486. example: FormFeed
  2487.          --or--
  2488.          Call FormFeed
  2489.  
  2490. SUBROUTINE: WarmBoot
  2491. Performs a WARM boot on the PC like typing Ctrl-Alt-Del. (no memory check)
  2492. example: WarmBoot
  2493.          --or--
  2494.          Call WarmBoot
  2495.  
  2496. APPENDIX A - KEYCODE VALUES RETURNED BY THE KEYBOARD FUNCTIONS
  2497.              (1O1-Key Keyboard)
  2498.              Note: The special function keys return (negative of scan_code)
  2499.  
  2500.             ┌─────┬─────┬─────┬─────┐             ┌─────┬─────┬─────┬─────┐
  2501.        key  │     │SHIFT│ CTRL│ ALT │        key  │     │SHIFT│ CTRL│ ALT │
  2502.     ┌───────┼─────┼─────┼─────┼─────┤     ┌───────┼─────┼─────┼─────┼─────┤
  2503.     │   A   │* 97 │  65 │   1 │ -3O │     │  ESC  │  27 │  27 │  27 │  ∙  │
  2504.     │   B   │  98 │  66 │   2 │ -48 │     │ BKSP  │   8 │   8 │ 127 │  ∙  │
  2505.     │   C   │  99 │  67 │   3 │ -46 │     │  TAB  │   9 │ -15 │  ∙  │  ∙  │
  2506.     │   D   │ 1OO │  68 │   4 │ -32 │     │ SPACE │  32 │  32 │  32 │  32 │
  2507.     │   E   │ 1O1 │  69 │   5 │ -18 │     │ ENTER │  13 │  13 │  1O │  ∙  │
  2508.     │   F   │ 1O2 │  7O │   6 │ -33 │     │  F1   │ -59 │ -84 │ -94 │-1O4 │
  2509.     │   G   │ 1O3 │  71 │   7 │ -34 │     │  F2   │ -6O │ -85 │ -95 │-1O5 │
  2510.     │   H   │ 1O4 │  72 │   8 │ -35 │     │  F3   │ -61 │ -86 │ -96 │-1O6 │
  2511.     │   I   │ 1O5 │  73 │   9 │ -23 │     │  F4   │ -62 │ -87 │ -97 │-1O7 │
  2512.     │   J   │ 1O6 │  74 │  1O │ -36 │     │  F5   │ -63 │ -88 │ -98 │-1O8 │
  2513.     │   K   │ 1O7 │  75 │  11 │ -37 │     │  F6   │ -64 │ -89 │ -99 │-1O9 │
  2514.     │   L   │ 1O8 │  76 │  12 │ -38 │     │  F7   │ -65 │ -9O │-1OO │-11O │
  2515.     │   M   │ 1O9 │  77 │  13 │ -5O │     │  F8   │ -66 │ -91 │-1O1 │-111 │
  2516.     │   N   │ 11O │  78 │  14 │ -49 │     │  F9   │ -67 │ -92 │-1O2 │-112 │
  2517.     │   O   │ 111 │  79 │  15 │ -24 │     │  F1O  │ -68 │ -93 │-1O3 │-113 │
  2518.     │   P   │ 112 │  8O │  16 │ -25 │     │  F11  │  ∙  │  ∙  │  ∙  │  ∙  │
  2519.     │   Q   │ 113 │  81 │  17 │ -16 │     │  F12  │  ∙  │  ∙  │  ∙  │  ∙  │
  2520.     │   R   │ 114 │  82 │  18 │ -19 │     │ UP    │ -72 │ -72 │  ∙  │  ∙  │
  2521.     │   S   │ 115 │  83 │  19 │ -31 │     │ DOWN  │ -8O │ -8O │  ∙  │  ∙  │
  2522.     │   T   │ 116 │  84 │  2O │ -2O │     │ LEFT  │ -75 │ -75 │-115 │  ∙  │
  2523.     │   U   │ 117 │  85 │  21 │ -22 │     │ RIGHT │ -77 │ -77 │-116 │  ∙  │
  2524.     │   V   │ 118 │  86 │  22 │ -47 │     │ INS   │ -82 │ -82 │  ∙  │  ∙  │
  2525.     │   W   │ 119 │  87 │  23 │ -17 │     │ DEL   │ -83 │ -83 │  ∙  │  ∙  │
  2526.     │   X   │ 12O │  88 │  24 │ -45 │     │ HOME  │ -71 │ -71 │-119 │  ∙  │
  2527.     │   Y   │ 121 │  89 │  25 │ -21 │     │ END   │ -79 │ -79 │-117 │  ∙  │
  2528.     │   Z   │ 122 │  9O │  26 │ -44 │     │ PGUP  │ -73 │ -73 │ 1O1 │  ∙  │
  2529.     │ O or )│  48 │  41 │  ∙  │-129 │     │ PGDN  │ -81 │ -81 │-118 │  ∙  │
  2530.     │ 1 or !│  49 │  33 │  ∙  │-12O │     │ - or _│  45 │  95 │  31 │-13O │
  2531.     │ 2 or @│  5O │  64 │ -3  │-121 │     │ + or =│  61 │  43 │  ∙  │-131 │
  2532.     │ 3 or #│  51 │  35 │  ∙  │-122 │     │ | or \│  92 │ 124 │  28 │  ∙  │
  2533.     │ 4 or $│  52 │  36 │  ∙  │-123 │     │ { or [│  91 │ 123 │  27 │  ∙  │
  2534.     │ 5 or %│  53 │  37 │  ∙  │-124 │     │ ] or }│  93 │ 125 │  29 │  ∙  │
  2535.     │ 6 or ^│  54 │  94 │  3O │-125 │     │ : or ;│  59 │  58 │  ∙  │  ∙  │
  2536.     │ 7 or &│  55 │  38 │  ∙  │-126 │     │ " or '│  39 │  34 │  ∙  │  ∙  │
  2537.     │ 8 or *│  56 │  42 │  ∙  │-127 │     │ < or ,│  44 │  6O │  ∙  │  ∙  │
  2538.     │ 9 or (│  57 │  4O │  ∙  │-128 │     │ > or .│  46 │  62 │  ∙  │  ∙  │
  2539.     │ ` or ~│  96 │ 126 │  ∙  │  ∙  │     │ ? or /│  47 │  63 │  ∙  │  ∙  │
  2540.     └───────┴─────┴─────┴─────┴─────┘     └───────┴─────┴─────┴─────┴─────┘
  2541.     * indicates keycode for lower-case alphabetic characters
  2542.       for example:  a=97   A=65
  2543.                     z=122  Z=9O
  2544.  
  2545. ┌──────────────────────────────────────────────────────────────────────────────┐
  2546. │ APPENDIX B          FADES for the ScreenFade Subroutine                      │
  2547. ├──────────────────┬┬──────────────────┬┬──────────────────┬┬──────────────────┤
  2548. │ O Quick          ││19 Spiral CW In   ││38 Wipe V Close   ││57 Circ Sweep Down│
  2549. │ 1 Fizz           ││2O Spiral CW Out  ││39 Half Wipe V U/D││58 Circ Sweep Up  │
  2550. │ 2 Melt Down      ││21 Spiral CCW In  ││4O Half Wipe V D/U││59 Radar CW       │
  2551. │ 3 Melt Up        ││22 Spiral CCW Out ││41 Half Wipe H L/R││6O Radar CCW      │
  2552. │ 4 Liquid Flow Dn ││23 Mult Sp CW In  ││42 Half Wipe H R/L││61 Louver H Large │
  2553. │ 5 Liquid Flow Up ││24 Mult Sp CW Out ││43 Checker Down   ││62 Louver H Small │
  2554. │ 6 Quarters - CW  ││25 Mult Sp CCW In ││44 Checker Up     ││63 Louver V Large │
  2555. │ 7 Quarters - CCW ││26 Mult Sp CCW Out││45 Diagonal Right ││64 Louver V Small │
  2556. │ 8 Quarters - Alt ││27 Wipe Down      ││46 Diagonal Left  ││                  │
  2557. │ 9 Blks Random Lg ││28 Wipe Up        ││47 Chckr Lvr 1step││                  │
  2558. │1O Blks Random Sm ││29 Wipe Right     ││48 Chckr Lvr 2step││                  │
  2559. │11 Zigzag H Lg Rt ││3O Wipe Left      ││49 Diagonal Lvr R ││                  │
  2560. │12 Zigzag H Lg Lft││31 Curtain H Open ││5O Diagonal Lvr L ││                  │
  2561. │13 Zigzag H Sm Rt ││32 Curtain H Close││51 Page Feed Down ││                  │
  2562. │14 Zigzag H Sm Lft││33 Curtain V Open ││52 Page Feed Up   ││                  │
  2563. │15 Zigzag V Down  ││34 Curtain V Close││53 Page Feed Right││                  │
  2564. │16 Zigzag V Up    ││35 Wipe H Open    ││54 Page Feed Left ││255 selects a     │
  2565. │17 Orifice Open   ││36 Wipe H Close   ││55 Circ Sweep CW  ││    random fade   │
  2566. │18 Orifice Close  ││37 Wipe V Open    ││56 Circ Sweep CCW ││    from this list│
  2567. └──────────────────┴┴──────────────────┴┴──────────────────┴┴──────────────────┘
  2568. Note: The program FADES.EXE will demonstrate each of these fades.
  2569.  
  2570.  
  2571.